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 }

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5141

posted on 2014-12-12 00:36  xiao_xin  阅读(139)  评论(0编辑  收藏  举报

导航