bzoj 4553: [Tjoi2016&Heoi2016]序列
不得不说这道题还是很劲的(在我这个蒟蒻看来)
摘自某神犇题解:对于每一次修改,只有序列中数值可以变成的最大值和最小值是有影响的。那么这就可以决定,有这样的一个方程
f[i]=max(f[j])+1 其中,a[i]>=mx[j] && nm[i]>=a[j] 这样的话就保证了在所有的修改中,从f[j]转移到f[i]是始终成立的。
那么,这样一共就有mn,mx,a三个值需要比较了。
三位偏序,上CDQ!!题解好强!!!
1 #include <bits/stdc++.h> 2 using namespace std; 3 inline int ra() 4 { 5 int x=0; char ch=getchar(); 6 while (ch<'0' || ch>'9') ch=getchar(); 7 while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} 8 return x; 9 } 10 11 const int maxn=100005; 12 13 int c[maxn]; 14 struct node{ 15 int mx,mn,v,id; 16 }a[maxn]; 17 int f[maxn],ans,n,m; 18 19 bool cmp_mn(node a, node b) {return a.mn<b.mn;} 20 bool cmp_id(node a, node b) {return a.id<b.id;} 21 22 int lowbit(int x) {return x&(-x);} 23 void add(int x, int val) 24 { 25 for (;x<maxn;x+=lowbit(x)) c[x]=max(c[x],val); 26 } 27 int ask(int x) 28 { 29 int mx=0; 30 for (;x;x-=lowbit(x)) mx=max(mx,c[x]); 31 return mx; 32 } 33 void clear(int x) {for (;x<maxn; x+=lowbit(x)) c[x]=0;} 34 35 node t[maxn]; 36 void solve(int l, int r) 37 { 38 if (l>=r) return; 39 int mid=l+r>>1; 40 solve(l,mid); 41 int tmp=l; sort(a+mid+1,a+r+1,cmp_mn); 42 for (int i=mid+1; i<=r; i++) 43 { 44 while (tmp<=mid && a[tmp].v<=a[i].mn) add(a[tmp].mx,f[a[tmp].id]),tmp++; 45 f[a[i].id]=max(f[a[i].id],ask(a[i].v)+1); 46 } 47 for (int i=l; i<tmp; i++) clear(a[i].mx); 48 sort(a+mid+1,a+r+1,cmp_id); 49 solve(mid+1,r); 50 int L=l,R=mid+1; tmp=l; 51 while (L<=mid && R<=r) t[tmp++]=a[L].v<a[R].v?a[L++]:a[R++]; 52 while (L<=mid) t[tmp++]=a[L++]; 53 while (R<=r) t[tmp++]=a[R++]; 54 for (int i=l; i<=r; i++) a[i]=t[i]; 55 } 56 57 int main() 58 { 59 n=ra(); m=ra(); 60 for (int i=1; i<=n; i++) a[i].v=a[i].mn=a[i].mx=ra(),a[i].id=i,f[i]=1; 61 for (int i=1; i<=m; i++) 62 { 63 int x=ra(),y=ra(); 64 a[x].mn=min(a[x].mn,y); 65 a[x].mx=max(a[x].mx,y); 66 } 67 solve(1,n); 68 for (int i=1; i<=n; i++) ans=max(ans,f[i]); 69 cout<<ans<<endl; 70 return 0; 71 }