项链工厂
项链工厂
题解
一道线段树的题,但是笔者还是用FHQ_Treap写了,虽然调得想吐,这就是拿大数据一个一个比对的结果。
虽说这是一个环,但我们还是可以采取链的方式维护,最后再特判两端的情况即可。
先来分析一下每个操作的情况。
对于P操作,我们可以将其分为前n-k个与后k个两棵子树,将其反过来合并即可。
对于F操作,没必要去想那些奇偶性判断,直接将后n-1个倒置过来即可。
对于S操作,将i点与j点单独分出来,交换位置后再合并就可以了。
对于P操作,需分与
两种情况来判断,覆盖掉分出来的部分即可。
对于C操作,直接输出过程中维护的和即可。
对于CS操作,我们可以也需分与
两种情况来处理,输出需要求的一块或两块和即可。
记住!!!不要在外面单独判断C或CS中需要求出整段和时两端相同的情况,尽量在updata中。笔者因为的特判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;
}

浙公网安备 33010602011771号