用max[i]代表i位置变化最大值,min[i]代表i位置变化最小值
搞出偏序关系,j<=i, max[j] <=a[i], a[j] <= min[i]
这里用的是KDtree求偏序。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1000100;
struct node
{
int d[2],mx[2],mn[2],l,r,val,mxv;
int & operator [](int x){return d[x];}
node (int x=0,int y=0,int z=0)
{
d[0]=x;d[1]=y;val=z;l=0;r=0;
}
} p[maxn];
int n,m,D;
int mx[maxn],mn[maxn],a[maxn],f[maxn],x,y;
bool operator < (node a,node b)
{
return a[D]<b[D]||(a[D]==b[D]&&a[!D]<b[!D]);
}
int root,res,cnt;
struct kd_tree
{
node t;
void update(int x)
{
node l=p[p[x].l],r=p[p[x].r];
for(int i=0;i<2;i++)
{
p[x].mn[i]=p[x].mx[i]=p[x][i];
if(p[x].l) p[x].mn[i]=min(p[x].mn[i],l.mn[i]),p[x].mx[i]=max(p[x].mx[i],l.mx[i]);
if(p[x].r) p[x].mn[i]=min(p[x].mn[i],r.mn[i]),p[x].mx[i]=max(p[x].mx[i],r.mx[i]);
}
p[x].mxv=max(p[x].val,max(l.mxv,r.mxv));
}
int build(int l,int r,int now){
if(l>r) return 0;
D=now;
int mid=(l+r)>>1;
nth_element(p+l,p+mid,p+r+1);
p[mid].l=build(l,mid-1,now^1);
p[mid].r=build(mid+1,r,now^1);
update(mid);
return mid;
}
void insert(int &x,bool d){
if(!x){
x=++cnt;
p[x][0]=t[0],p[x][1]=t[1];
}
if(t[0]==p[x][0]&&t[1]==p[x][1]){
p[x].val=max(p[x].val,t.val);
p[x].mxv=max(p[x].mxv,t.val);
return;
}
D=d;
if(t<p[x]) insert(p[x].l,!d);
else insert(p[x].r,!d);
update(x);
}
bool in(int x,int y,int X,int Y){return x<=X&&y<=Y;}
bool out(int x,int y,int X,int Y){return x>X||y>Y;}
int query(int x,int xm,int ym){
if(!x) return 0;
if(in(p[x].mx[0],p[x].mx[1],xm,ym)) return p[x].mxv;
if(out(p[x].mn[0],p[x].mn[1],xm,ym)) return 0;
int ans=-1,ans1=-1;
if(in(p[x][0],p[x][1],xm,ym)) ans=p[x].val;
if(p[p[x].l].mxv>ans) ans1=query(p[x].l,xm,ym);
ans=max(ans,ans1);ans1=-1;
if(p[p[x].r].mxv>ans) ans1=query(p[x].r,xm,ym);
ans=max(ans,ans1);
return ans;
}
void work(){
cnt=n;
for(int i=1;i<=n;i++) p[i]=node(mx[i],a[i],0);
root=build(0,n,0);
for(int i=1;i<=n;i++)
{
f[i]=query(root,a[i],mn[i])+1;
t=node(mx[i],a[i],f[i]);
insert(root,0);
if(res<f[i]) res=f[i];
}
printf("%d\n",res);
}
}kd;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
mx[i]=mn[i]=a[i];
}
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
mx[x]=max(mx[x],y);
mn[x]=min(mn[x],y);
}
kd.work();
return 0;
}
/*
3 4
1 2 3
1 2
2 3
2 1
3 4
*/