题解:
发现多决策且明显无后效性,果断dp,那么转移方程F[i]=F[j]+1
设R[I]为改变之后的最大值,L[i]为改变之后的最小值
由于只能改变一个元素 所以转移的条件是 (j<i && R[j]<a[i] && a[j]<L[i]) 写成这样 就光然大悟 裸三维偏序诶
于是CDQ 乱搞即可 人懒不想打归并...
1 #include <algorithm> 2 #include <iostream> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <cmath> 7 using namespace std; 8 const int N=100005,INF=2e8; 9 int gi(){ 10 int str=0;char ch=getchar(); 11 while(ch>'9' || ch<'0')ch=getchar(); 12 while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar(); 13 return str; 14 } 15 int n,m,f[N]; 16 struct node{ 17 int x,L,R,id; 18 }a[N]; 19 bool compid(const node &px,const node &qx){ 20 return px.id<qx.id; 21 } 22 bool compL(const node &px,const node &qx){ 23 return px.L<qx.L; 24 } 25 bool compx(const node &px,const node &qx){ 26 return px.x<qx.x; 27 } 28 int Tree[N<<1],st[N<<1],top=0; 29 void add(int sta,int x){ 30 for(int i=sta;i<=n;i+=(i&(-i))){if(x>Tree[i])Tree[i]=x;} 31 } 32 int query(int sta){ 33 int ret=0; 34 for(int i=sta;i>=1;i-=(i&(-i)))if(Tree[i]>ret)ret=Tree[i]; 35 return ret; 36 } 37 void Clear(int sta){ 38 for(int i=sta;i<=n;i+=(i&(-i)))Tree[i]=0; 39 } 40 int ans=0; 41 void cdq(int l,int r){ 42 if(l==r)return ; 43 int mid=(l+r)>>1; 44 cdq(l,mid); 45 sort(a+l,a+mid+1,compx);sort(a+mid+1,a+r+1,compL); 46 int t1=l,t2=mid+1; 47 while(t1<=mid && t2<=r){ 48 if(a[t1].x<=a[t2].L)st[++top]=a[t1].R,add(a[t1].R,f[a[t1].id]),t1++; 49 else f[a[t2].id]=max(f[a[t2].id],query(a[t2].x)+1),t2++; 50 } 51 while(t2<=r){ 52 f[a[t2].id]=max(f[a[t2].id],query(a[t2].x)+1);t2++; 53 } 54 while(top)Clear(st[top--]); 55 sort(a+mid+1,a+r+1,compid); 56 cdq(mid+1,r); 57 } 58 void work(){ 59 int x,y; 60 n=gi();m=gi(); 61 for(int i=1;i<=n;i++)a[i].x=gi(),a[i].L=a[i].R=a[i].x,a[i].id=i,f[i]=1; 62 for(int i=1;i<=m;i++){ 63 x=gi();y=gi(); 64 if(y>a[x].R)a[x].R=y; 65 if(y<a[x].L)a[x].L=y; 66 } 67 cdq(1,n); 68 for(int i=1;i<=n;i++)if(f[i]>ans)ans=f[i]; 69 printf("%d ",ans); 70 } 71 int main() 72 { 73 freopen("heoi2016_seq.in","r",stdin); 74 freopen("heoi2016_seq.out","w",stdout); 75 work(); 76 return 0; 77 }