[HNOI2016]序列 CDQ+DP

[HNOI2016]序列 CDQ

链接

loj

思路

一个点最小变为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
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/dsrdsr/p/11218742.html