hdu5141 子序列LIS==原序列LIS的子序列个数(nlogn)
比较巧妙的做法,动态维护最右起点,然后用p[i]表示到i时的LIS的最右起点,好吧有点拗口==
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define LL long long 5 using namespace std; 6 int w[100005],a[100005],c[100005],p[100005],l[100005]; 7 //分别最右起点,输入,所维护的nlogn,i对应最右起点,最长上升长度 8 int main() 9 { 10 int n,i,len,j,maxx; 11 LL ans; 12 while (~scanf("%d",&n)) 13 { 14 for (i=1;i<=n;i++) 15 scanf("%d",&a[i]); 16 memset(w,-1,sizeof(w)); 17 c[1]=a[1]; l[1]=len=w[1]=p[1]=1; 18 for (i=2;i<=n;i++) 19 { 20 j=lower_bound(c+1,c+len+1,a[i])-c; 21 c[j]=a[i]; 22 if (j==1) w[j]=i; 23 else w[j]=max(w[j-1],w[j]); 24 p[i]=w[j]; l[i]=j; 25 if (j>len) len=j; 26 } 27 maxx=0; ans=0; 28 for (i=1;i<=n;i++) 29 { 30 if (l[i]==len) maxx=max(maxx,p[i]); 31 ans=ans+maxx; 32 } 33 printf("%I64d\n",ans); 34 } 35 return 0; 36 }