我们发现
三维偏序问题用CDQ分治实现
对于[L-R]区间的DP的值, 我们先递归处理[L-Mid]
然后用[L-Mid]的值更新 [Mid+1-R], 最后递归处理[Mid+1 - R]
中途左边按a[i]排序, 右边按Min[i]排序, 然后两个指针扫就可以了
#include<bits/stdc++.h>
#define N 100050
using namespace std;
int n,m,c[N];
struct Node{
int val, Max, Min, id, f;
}q[N];
bool cmpMin(Node a, Node b){ return a.Min < b.Min;}
bool cmpval(Node a, Node b){ return a.val < b.val;}
bool cmpid(Node a, Node b){ return a.id < b.id;}
int read(){
int cnt = 0; char ch = 0;
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) cnt = cnt * 10 + (ch-'0'), ch = getchar();
return cnt;
}
void add(int x,int val){ for(;x<=N-50;x+=x&-x) c[x] = max(c[x],val); }
int quary(int x){int ans=0; for(;x;x-=x&-x) ans = max(ans, c[x]); return ans;}
void clear(int x){ for(;x<=N-50;x+=x&-x) c[x] = 0;}
void CDQ(int l,int r){
if(l==r) return;
int mid = (l+r) >> 1;
CDQ(l,mid);
sort(q+l, q+mid+1, cmpval);
sort(q+mid+1, q+r+1, cmpMin);
int i = l, j = mid+1;
for(;j<=r;j++){
while(i<=mid && q[j].Min >= q[i].val) add(q[i].Max, q[i].f), i++;
q[j].f = max(q[j].f, quary(q[j].val) + 1);
}
for(i=l;i<=mid;i++) clear(q[i].Max);
sort(q+l,q+r+1,cmpid);
CDQ(mid+1,r);
}
int main(){
n = read(), m = read();
for(int i=1;i<=n;i++){
int x = read();
q[i] = (Node){x, x, x, i, 1};
}
for(int i=1;i<=m;i++){
int x = read(), val = read();
q[x].Min = min(q[x].Min, val);
q[x].Max = max(q[x].Max, val);
}
CDQ(1,n); int ans = 0;
for(int i=1;i<=n;i++) ans = max(ans, q[i].f);
printf("%d",ans); return 0;
}