bzoj5157: [Tjoi2014]上升子序列(树状数组LIS)

5157: [Tjoi2014]上升子序列

题目:传送门


 

题解:

   学一下nlogn的树状数组求最长上生子序列就ok(%爆大佬

   离散化之后,用一个数组记录一下,直接树状数组做

   吐槽:妈耶...一开始不会lower_bound 的蒟蒻用手打二分离散化...结果去重了...然后屁颠屁颠的学了lower_bound(很好用!)

 


代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<algorithm>
 6 #define mod 1000000007
 7 using namespace std;
 8 int n,a[110000],wa[110000],s[110000];
 9 int lowbit(int x){return x&-x;}
10 void add(int x,int p)
11 {
12     while(x<=n)
13     {
14         s[x]=(s[x]+p)%mod;
15         x+=lowbit(x);
16     }
17 }
18 int getsum(int x)
19 {
20     int ans=0;
21     while(x)
22     {
23         ans=(ans+s[x])%mod;
24         x-=lowbit(x);
25     }
26     return ans;
27 }/*
28 int LS(int x)
29 {
30     int l,r,mid,ans;
31     l=1,r=n;
32     while(l<=r)
33     {
34         mid=(l+r)/2;
35         if(wa[mid]<=x)
36         {
37             l=mid+1;
38             ans=mid;
39         }
40         else r=mid-1;
41     }
42     return ans;
43 }*/
44 int f[110000],last[110000],w[110000];
45 int main()
46 {
47     scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),wa[i]=a[i];
48     sort(wa+1,wa+n+1);int sum=0;memset(f,0,sizeof(f));
49     for(int i=1;i<=n;i++)
50     {
51         a[i]=lower_bound(wa+1,wa+n+1,a[i])-wa;if(w[a[i]]==0)sum++;
52         last[i]=w[a[i]];w[a[i]]=i;//链表记录上次影响的位置 
53     }
54     for(int i=1;i<=n;i++)
55     {
56         f[i]=getsum(a[i]-1)+1;//这个数能贡献的上升子序列个数 
57         add(a[i],(f[i]-f[last[i]]+mod)%mod);//减去重复的贡献 
58     }
59     int ans=getsum(n);
60     printf("%d\n",(ans-sum+mod)%mod);
61     return 0;
62 }

 

posted @ 2018-03-10 09:09  CHerish_OI  阅读(158)  评论(0编辑  收藏  举报