项链工厂

项链工厂

题解

一道线段树的题,但是笔者还是用FHQ_Treap写了,虽然调得想吐,这就是拿大数据一个一个比对的结果

虽说这是一个环,但我们还是可以采取链的方式维护,最后再特判两端的情况即可。

先来分析一下每个操作的情况。

对于P操作,我们可以将其分为前n-k个与后k个两棵子树,将其反过来合并即可。

对于F操作,没必要去想那些奇偶性判断,直接将后n-1个倒置过来即可。

对于S操作,将i点与j点单独分出来,交换位置后再合并就可以了。

对于P操作,需分x \leq yx> y两种情况来判断,覆盖掉分出来的部分即可。

对于C操作,直接输出过程中维护的和即可。

对于CS操作,我们可以也需分x\leq yx> y两种情况来处理,输出需要求的一块或两块和即可。

记住!!!不要在外面单独判断C或CS中需要求出整段和时两端相同的情况,尽量在updata中。笔者因为x= y+1的特判WA了半天,最后全放在updata中维护就没事儿了。

源码

数据解构真的难调!!!

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXN 1000005
using namespace std;
typedef long long LL;
const int INF=0x7f7f7f7f;
#define gc() getchar()
int son[MAXN][2],tot,rt;
int rnd[MAXN],siz[MAXN],q,n,c;
bool tag[MAXN];
int val[MAXN],ad[MAXN],cov[MAXN];
int pre[MAXN],re[MAXN],sum[MAXN];
template<typename _T>
inline void read(_T &x){
	_T f=1;x=0;char s=gc();
	while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
	while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
	x*=f;
} 
template<typename _T>
void write(_T x)
{
	if(x<0) x=~x+1,putchar('-');
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
int newnode(int v){
	int x=++tot;
	siz[x]=1;rnd[x]=rand();sum[x]=1;
	pre[x]=re[x]=val[x]=v;cov[x]=0;
	tag[x]=son[x][0]=son[x][1]=0;
	return x;
}
void reverse(int x){
	swap(son[x][0],son[x][1]);
	swap(pre[x],re[x]);
	tag[x]^=1;
}
void updata(int x){
	siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
	if(son[x][0]) pre[x]=pre[son[x][0]];
	else pre[x]=val[x];
	if(son[x][1]) re[x]=re[son[x][1]];
	else re[x]=val[x];
	sum[x]=1;
	if(re[son[x][0]]!=val[x]) sum[x]+=sum[son[x][0]];
	else sum[x]+=sum[son[x][0]]-1;
	if(pre[son[x][1]]!=val[x]) sum[x]+=sum[son[x][1]];
	else sum[x]+=sum[son[x][1]]-1;
	if(siz[x]==n&&pre[x]==re[x]&&sum[x]!=1) sum[x]--;
}
void covered(int x,int d){
	cov[x]=val[x]=d;
	pre[x]=re[x]=d;sum[x]=1;
}
void downdata(int x){
	if(tag[x]){
		if(son[x][0]) reverse(son[x][0]);
		if(son[x][1]) reverse(son[x][1]);
		tag[x]^=1;
	}
	if(cov[x]){
		if(son[x][0]) covered(son[x][0],cov[x]);
		if(son[x][1]) covered(son[x][1],cov[x]);
		cov[x]=0;
	}
}
void build(int &p,int l,int r){
	if(l>r) return ;
	int mid=(l+r)>>1;p=newnode(ad[mid]);
	build(son[p][0],l,mid-1);
	build(son[p][1],mid+1,r);
	updata(p);
	//printf("%d %d %d\n",l,r,minn[p]);
}
int merge(int a,int b){
	if(!a||!b) return a+b;
	downdata(a);downdata(b);
	if(rnd[a]<rnd[b]){
		son[a][1]=merge(son[a][1],b);
		updata(a);return a;
	}	
	son[b][0]=merge(a,son[b][0]);
	updata(b);return b;
}
void split(int now,int k,int &x,int &y){
	if(!now){
		x=y=0;
		return ;
	}
	downdata(now);
	if(k<=siz[son[now][0]]) 
		y=now,split(son[now][0],k,x,son[now][0]);
	else x=now,split(son[now][1],k-siz[son[now][0]]-1,son[now][1],y);
	updata(now);
}
signed main()
{
	read(n);read(c);
	for(int i=1;i<=n;i++) read(ad[i]);
	build(rt,1,n);read(q);
	for(int i=1;i<=q;i++){
		char opt[15]={};scanf("%s",opt);
		if(opt[0]=='F'){
			int xa,ya;split(rt,1,xa,ya);
			reverse(ya);rt=merge(xa,ya);
		}
		if(opt[0]=='R'){
			int k,xa,ya;read(k);
			split(rt,n-k,xa,ya);rt=merge(ya,xa);
		}
		if(opt[0]=='S'){
			int x,y,xa,xb,ya,yb,xc,yc,xd,yd;read(x);read(y);
			if(x>y) swap(x,y);
			if(x==y) continue;
			split(rt,y,xa,ya);split(xa,y-1,xb,yb);
			split(xb,x,xc,yc);split(xc,x-1,xd,yd);
			rt=merge(merge(merge(xd,yb),yc),merge(yd,ya));
		}
		if(opt[0]=='P'){
			int x,y,z;read(x);read(y);read(z);
			if(x<=y){
				int xa,ya,xb,yb;
				split(rt,y,xa,ya);split(xa,x-1,xb,yb);
				covered(yb,z);rt=merge(merge(xb,yb),ya);
			}
			else{
				int xa,ya,xb,yb;
				split(rt,x-1,xa,ya);split(xa,y,xb,yb);
				covered(xb,z);covered(ya,z);rt=merge(merge(xb,yb),ya);
			}
		}
		if(opt[0]=='C'&&opt[1]!='S') printf("%d\n",sum[rt]);
		if(opt[0]=='C'&&opt[1]=='S'){
			int x,y;read(x);read(y);
			if(x<=y){
				int xa,ya,xb,yb;
				if(x!=1||y!=n) {
					split(rt,y,xa,ya);split(xa,x-1,xb,yb);
					printf("%d\n",sum[yb]);
					rt=merge(merge(xb,yb),ya);
				}
				else printf("%d\n",sum[rt]);
			}
			else{
				int xa,ya,xb,yb;
				split(rt,x-1,xa,ya);split(xa,y,xb,yb);
				if(re[ya]!=pre[xb]) printf("%d\n",sum[ya]+sum[xb]);
				else printf("%d\n",sum[ya]+sum[xb]-1);
				rt=merge(merge(xb,yb),ya);
			}
		}
	}
	return 0;
}

谢谢!!

posted @ 2019-11-30 16:31  StaroForgin  阅读(10)  评论(0)    收藏  举报  来源