题目

Description
【笛卡尔树+DP】随机的排列_题组

Input
【笛卡尔树+DP】随机的排列_题组_02

Output
【笛卡尔树+DP】随机的排列_题组_03

Sample Input
5 1
2 4 1 5 3
2

Sample Output
2
2

Data Constraint

【笛卡尔树+DP】随机的排列_题组_04
【笛卡尔树+DP】随机的排列_题组_05

思路

我们可以先对序列建立一棵笛卡尔树。
建法就是每一次找到区间中的最大值,然后把这个点作为根。这样这个点的左子树就是以这个点切开的左区间,而右子树就是以这个点切开的右区间。
可以发现,一个点连边的点的集合为这个点左子树的最右侧的一条链和这个点右子树最靠左的一条链。这个时候就可以DP了。

考虑修改,因为数据是随机的,所以笛卡尔树的高度不超过log,所以我们只有log个DP值会更新

代码

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+77;
int a[N],lson[N],rson[N],fa[N],f[N][2][2][2],n,q,root;
void calc(int k)
{
	f[k][0][0][0]=f[lson[k]][0][0][1]+f[rson[k]][0][1][0];
	f[k][0][1][0]=f[lson[k]][1][1][1]+f[rson[k]][0][1][0];
	f[k][0][0][1]=f[lson[k]][0][0][1]+f[rson[k]][1][1][1];
	f[k][0][1][1]=f[lson[k]][1][1][1]+f[rson[k]][1][1][1];
	f[k][1][0][0]=f[lson[k]][0][0][0]+f[rson[k]][0][0][0]+1;
	f[k][1][1][0]=f[lson[k]][0][1][0]+f[rson[k]][0][0][0]+1;
	f[k][1][0][1]=f[lson[k]][0][0][0]+f[rson[k]][0][0][1]+1;
	f[k][1][1][1]=f[lson[k]][0][1][0]+f[rson[k]][0][0][1]+1;
	for(int x=1; x>=0; x--)
		for(int y=1; y>=0; y--)
			for(int z=1; z>=0; z--)
			{
				if(x==1&&f[k][0][y][z]>f[k][1][y][z]) f[k][0][y][z]=f[k][1][y][z];
				if(y==1&&f[k][x][0][z]>f[k][x][1][z]) f[k][x][0][z]=f[k][x][1][z];
				if(z==1&&f[k][x][y][0]>f[k][x][y][1]) f[k][x][y][0]=f[k][x][y][1];
			}
}
void dfs(int k)
{
	if(lson[k]) dfs(lson[k]);
	if(rson[k]) dfs(rson[k]);
	calc(k);
}
void solve()
{
	for(int i=0; i<=n; i++)
	{
		lson[i]=0,rson[i]=0,fa[i]=0;
		for(int x=0; x<=1; x++) for(int y=0; y<=1; y++) for(int z=0; z<=1; z++) f[i][x][y][z]=0;
	}
	root=a[1];
	for(int i=2; i<=n; i++)
	{
		if(a[i]>root) lson[a[i]]=root,fa[root]=a[i],root=a[i];
		else
		{
			int j;
			for(j=root; a[i]<rson[j]; j=rson[j]);
			if(rson[j]) lson[a[i]]=rson[j],fa[rson[j]]=a[i];
			rson[j]=a[i],fa[a[i]]=j;
		}
	}
	dfs(root),printf("%d\n",f[root][1][1][1]);
}
int main()
{
	freopen("","r",stdin); freopen("permutation.out","w",stdout);
	scanf("%d%d",&n,&q);
	for(int i=1; i<=n; i++) scanf("%d",&a[i]);
	solve();
	while(q--)
	{
		int x,i,j; 
		scanf("%d",&x);
		if(a[x]<a[x+1])
		{
			if(a[x]==lson[a[x+1]])
			{
				fa[a[x]]=lson[a[x+1]]=0;
				if(lson[a[x]])
				{
					j=lson[a[x]],lson[a[x]]=0;
					fa[j]=a[x+1],lson[a[x+1]]=j;
				}
			}
			else
			{
				j=fa[a[x]],fa[a[x]]=0;
				if(lson[a[x]]) rson[j]=lson[a[x]],fa[rson[j]]=j,lson[a[x]]=0;
				else rson[j]=0;
				for(i=j; i!=a[x+1]; i=fa[i]) calc(i);
			}
			if(!rson[a[x+1]]) rson[a[x+1]]=a[x],fa[a[x]]=a[x+1];
			else if(a[x]>rson[a[x+1]])
			{
				j=rson[a[x+1]];
				rson[a[x]]=j,fa[j]=a[x];
				rson[a[x+1]]=a[x],fa[a[x]]=a[x+1];
			}
			else
			{
				for(i=rson[a[x+1]];a[x]<lson[i]; i=lson[i]);
				if(lson[i]) j=lson[i],rson[a[x]]=j,fa[j]=a[x];
				fa[a[x]]=i,lson[i]=a[x];
			}
			for(i=a[x]; i; i=fa[i]) calc(i);
		}
		else
		{
			if(a[x+1]==rson[a[x]])
			{
				fa[a[x+1]]=rson[a[x]]=0;
				if(rson[a[x+1]])
				{
					j=rson[a[x+1]],rson[a[x+1]]=0;
					fa[j]=a[x],rson[a[x]]=j;
				}
			}
			else
			{
				j=fa[a[x+1]],fa[a[x+1]]=0;
				if(rson[a[x+1]]) lson[j]=rson[a[x+1]],fa[lson[j]]=j,rson[a[x+1]]=0;
				else lson[j]=0;
				for(i=j; i!=a[x]; i=fa[i]) calc(i);
			}
			if(!lson[a[x]]) lson[a[x]]=a[x+1],fa[a[x+1]]=a[x];
			else if(a[x+1]>lson[a[x]])
			{
				j=lson[a[x]];
				lson[a[x+1]]=j,fa[j]=a[x+1];
				lson[a[x]]=a[x+1],fa[a[x+1]]=a[x];
			}
			else
			{
				for(i=lson[a[x]];a[x+1]<rson[i]; i=rson[i]);
				if(rson[i]) j=rson[i],lson[a[x+1]]=j,fa[j]=a[x+1];
				fa[a[x+1]]=i,rson[i]=a[x+1];
			}
			for(i=a[x+1]; i; i=fa[i]) calc(i);
		}
		swap(a[x],a[x+1]);
		printf("%d\n",f[root][1][1][1]);
	}
}