[HNOI2016]序列 CDQ+DP
[HNOI2016]序列 CDQ
链接
思路
一个点最小变为l,最大变为r,不变的时候为v
那么j能在i前面就要满足。
\(j<i\)
\(r[j]<=v[i]\)
\(v[j]<=l[i]\)
这个可以三位偏序CDQ优化DP。
代码
#include <bits/stdc++.h>
using namespace std;
const int _=1e5+7;
int n,m,f[_],ans;
struct node {int i,v,l,r;}a[_];
bool cmp0(node a,node b) {return a.v<b.v;}
bool cmp1(node a,node b) {return a.l<b.l;}
bool cmp2(node a,node b) {return a.i<b.i;}
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
namespace BIT {
int ma[_];
void add(int x,int val) {for(;x<=100000;x+=(x&(-x))) ma[x]=max(ma[x],val);}
void clear(int x) {for(;x<=100000;x+=(x&(-x))) ma[x]=0;}
int query(int x) {int ans=0;for(;x>=1;x-=(x&(-x))) ans=max(ans,ma[x]);return ans;}
}
void cdq(int l,int r) {
if(l==r) {f[l]=max(f[l],1);return;}
int mid=(l+r)>>1;
cdq(l,mid);
sort(a+l,a+mid+1,cmp0);
sort(a+mid+1,a+r+1,cmp1);
for(int i=mid+1,j=l;i<=r;++i) {
for(;a[j].v<=a[i].l&&j<=mid;j++)
BIT::add(a[j].r,f[a[j].i]);
f[a[i].i]=max(f[a[i].i],BIT::query(a[i].v)+1);
}
for(int i=l;i<=mid;++i) BIT::clear(a[i].r);
sort(a+mid+1,a+r+1,cmp2);
cdq(mid+1,r);
}
int main() {
n=read(),m=read();
for(int i=1;i<=n;++i) a[i].l=a[i].r=a[i].v=read(),a[i].i=i;
for(int i=1;i<=m;++i) {
int x=read(),y=read();
a[x].l=min(a[x].l,y);
a[x].r=max(a[x].r,y);
}
cdq(1,n);
for(int i=1;i<=n;++i) ans=max(ans,f[i]);
printf("%d\n",ans);
return 0;
}