cdq+dp

发布时间 2023-07-03 16:05:32作者: basicecho

P4093 [HEOI2016/TJOI2016]序列

/*
是在任意一种变化中,也就是一次只看一种变化 
那就没有时间顺序了

如果一次看所有的,会让我变得很小 

怎么都是左,中,右的结构 

确实是需要用到左中右
因为如果先计算右边的话,那么右边的数据是没有进行更新的
所以会对答案造成影响

可能也就只有dp才是这样子的

还是tm对维度进行划分的问题 
*/
#include <bits/stdc++.h>
using namespace std;

const int M=1e5+5;

int n,m;
int f[M];

struct node {
	int a,b,c,u;
}q[M],q0[M];

bool cmp1(node &u,node &v) {
	return u.a<v.a;
}

bool cmp2(node &u,node &v) {
	return u.b<v.b;
}

int lowbit(int x) {
	return x&-x;
}

int c[M];
void add(int i,int v) {
	while(i<=1e5) {
		if(v==-1)c[i]=0;
		else c[i]=max(c[i],v);
		i+=lowbit(i);
	}
}

int query(int i) {
	int ans=0;
	while(i) {
		ans=max(ans,c[i]);
		i-=lowbit(i);
	}
	return ans;
}

void cdq(int l,int r) {
	if(l==r)return ;
	int mid=(l+r)/2;
	cdq(l,mid);
	sort(q+l,q+mid+1,cmp1);
	sort(q+mid+1,q+r+1,cmp2);
	for(int i=mid+1,j=l;i<=r;i++) {
		while(j<=mid&&q[j].a<=q[i].b)
			add(q[j].c,f[q[j].u]),j++;
		f[q[i].u]=max(f[q[i].u],query(q[i].a)+1);
	}
	for(int i=l;i<=mid;i++)add(q[i].c,-1);
	for(int i=l;i<=r;i++)q[i]=q0[i];
	cdq(mid+1,r);
}

void solve() {
	cin>>n>>m;
	for(int i=1;i<=n;i++) {
		cin>>q[i].a;
		q[i].b=q[i].c=q[i].a;
		q[i].u=i;
	}
	for(int i=1;i<=m;i++) {
		int x,y;
		cin>>x>>y;
		q[x].b=min(q[x].b,y);
		q[x].c=max(q[x].c,y);
	}
	for(int i=1;i<=n;i++)f[i]=1,q0[i]=q[i];
	cdq(1,n);
	int ans=0;
	for(int i=1;i<=n;i++)ans=max(ans,f[i]);
	cout<<ans<<'\n';
}

signed main() {
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	solve();
	return 0;
}