设一个数的原值为v[i],最小能变化的值为l[i],最大值为r[i],观察一下可发现,i可放在j后面当且仅当r[j]<=v[i]且v[j]<=l[i],这样我们可以写出一个n^2的dp,dp中取max的过程相当于在左下角为(0,0),右上角为(v[i],l[i])的矩形内查询最大值,对f[i]赋值相当于在(r[i],v[i])加一个点,权值为f[i],这个过程可用树套树或KDT或CDQ分治实现
然而我写了一发树套树T了,今天模拟,考了一道题,也是dp最长某某某条件子序列转化为矩形最大值和加点,我又怒写一发树套树,结果又T了,xuruifan怒写KDT,T了,commonc怒写CDQ分治,过掉了-_-
然后当个双倍经验,我就写了这个CDQ分治
复杂度O(n log^2 n)
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 300010
#define MAXM 1010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
struct que{
int x;
int y;
int z;
int v;
bool cq;
friend bool operator <(que x,que y){
return x.x<y.x;
}
};
map<int,int>h;
int tls[MAXN],tln,mx;
int n,m;
int l[MAXN],r[MAXN],v[MAXN];
int T;
int f[MAXN];
int c[MAXN];
int vis[MAXN];
que a[MAXN],ta[MAXN];
inline int lb(int x){
return x&-x;
}
void change(int x,int y){
for(;x<=mx;x+=lb(x)){
if(vis[x]!=T){
c[x]=0;
}
vis[x]=T;
c[x]=max(c[x],y);
}
}
int ask(int x){
int re=0;
for(;x;x-=lb(x)){
if(vis[x]!=T){
c[x]=0;
}
vis[x]=T;
re=max(re,c[x]);
}
return re;
}
void cdq(int l,int r){
if(l==r){
if(!a[l].cq){
f[a[l].v]++;
}
return ;
}
int i,j,mid=l+r>>1,l1=l,l2=mid+1;
for(i=l;i<=r;i++){
if(a[i].z<=mid){
ta[l1++]=a[i];
}else{
ta[l2++]=a[i];
}
}
memcpy(a+l,ta+l,sizeof(que)*(r-l+1));
cdq(l,mid);
T++;
j=l;
for(i=mid+1;i<=r;i++){
for(;j<=mid&&a[j].x<=a[i].x;j++){
if(a[j].cq){
change(a[j].y,f[a[j].v]);
}
}
if(!a[i].cq){
f[a[i].v]=max(f[a[i].v],ask(a[i].y));
}
}
cdq(mid+1,r);
l1=l,l2=mid+1;
for(i=l;i<=r;i++){
if(a[l1]<a[l2]&&l1<=mid||l2>r){
ta[i]=a[l1++];
}else{
ta[i]=a[l2++];
}
}
memcpy(a+l,ta+l,sizeof(que)*(r-l+1));
}
int main(){
int i,x,y;
int tmp=0;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&v[i]);
l[i]=r[i]=v[i];
}
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
l[x]=min(l[x],y);
r[x]=max(r[x],y);
}
for(i=1;i<=n;i++){
tls[++tln]=v[i];
tls[++tln]=l[i];
tls[++tln]=r[i];
}
sort(tls+1,tls+tln+1);
for(i=1;i<=tln;i++){
if(tls[i]!=tls[i-1]){
h[tls[i]]=++mx;
}
}
for(i=1;i<=n;i++){
v[i]=h[v[i]];
l[i]=h[l[i]];
r[i]=h[r[i]];
}
int tim=0;
for(i=1;i<=n;i++){
a[++tim].z=tim;
a[tim].x=v[i];
a[tim].y=l[i];
a[tim].cq=0;
a[tim].v=i;
a[++tim].z=tim;
a[tim].x=r[i];
a[tim].y=v[i];
a[tim].cq=1;
a[tim].v=i;
}
sort(a+1,a+tim+1);
cdq(1,tim);
int ans=0;
for(i=1;i<=n;i++){
ans=max(ans,f[i]);
}
printf("%d\n",ans);
return 0;
}
/*
2 2
7 10
1 5
1 9
*/