5157: [Tjoi2014]上升子序列
题目:传送门
题解:
学一下nlogn的树状数组求最长上生子序列就ok
离散化之后,用一个数组记录一下,直接树状数组做
吐槽:妈耶...一开始不会lower_bound 的蒟蒻用手打二分离散化...结果去重了...然后屁颠屁颠的学了lower_bound(很好用!)
代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #define mod 1000000007 using namespace std; int n,a[110000],wa[110000],s[110000]; int lowbit(int x){return x&-x;} void add(int x,int p) { while(x<=n) { s[x]=(s[x]+p)%mod; x+=lowbit(x); } } int getsum(int x) { int ans=0; while(x) { ans=(ans+s[x])%mod; x-=lowbit(x); } return ans; }/* int LS(int x) { int l,r,mid,ans; l=1,r=n; while(l<=r) { mid=(l+r)/2; if(wa[mid]<=x) { l=mid+1; ans=mid; } else r=mid-1; } return ans; }*/ int v[110000],last[110000],pos[110000]; int main() { scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]),wa[i]=a[i]; sort(wa+1,wa+n+1);int sum=0; for(int i=1;i<=n;i++) { a[i]=lower_bound(wa+1,wa+n+1,a[i])-wa; if(pos[a[i]]==0)sum++; last[i]=pos[a[i]];pos[a[i]]=i; } for(int i=1;i<=n;i++) { v[i]=getsum(a[i]-1)+1;//这个数能贡献的上升子序列个数 add(a[i],(v[i]-v[last[i]]+mod)%mod);//减去重复的贡献 } int ans=getsum(n); printf("%d\n",(ans-sum+mod)%mod); return 0; }