FHQtreap,写挂,求助
查看原帖
FHQtreap,写挂,求助
697299
hamster000楼主2024/3/29 00:31
#include <bits/stdc++.h>
using namespace std;
//做法:注意到每个括号序列配对后都可以变成)))))(((((的形式
//记录每个序列的a,b进行求解。
struct edge{
	int l,r;
	int siz,key,val;
	int rep,swp,inv;
	int a,b;
	int a1,b1;
	//a1,b1为左右括号交换后的答案。
	//假设括号序列配对之后剩余a个左括号,b个右括号
	//容易想到右括号在序列最左侧,左括号在序列最右侧。
	//设右括号数量为a,左括号为b
}tr[100005];
int idx;
int newnode(int a,int b){
	tr[++idx].a=a;
	tr[idx].b=b;
	tr[idx].a1=b;
	tr[idx].b1=a;
	//左右括号交换后的答案
	tr[idx].key=rand();
	tr[idx].siz=1;
	return idx;
}

int root;

//对于操作1,打上区间修改标记即可。
//对于操作2,交换左右子树即可
//对于操作3,交换a和a1,b和b1即可
//对于操作4,答案就是a/2+a%2+b/2+b%2.

int query(int rt){
	int a=tr[rt].a,b=tr[rt].b;
	return a/2+b/2+a%2+b%2;
}

void pushdown(int rt){
	if(tr[rt].inv){
		swap(tr[rt].a,tr[rt].a1);
		swap(tr[rt].b,tr[rt].b1);
		tr[tr[rt].l].inv^=1;
		tr[tr[rt].r].inv^=1;
		tr[rt].inv=0;
	}if(tr[rt].rep){//1代表左括号,2代表右括号
		tr[tr[rt].l].rep=tr[rt].rep;
		tr[tr[rt].r].rep=tr[rt].rep;
		if(tr[rt].rep==1){
			tr[tr[rt].l].a=tr[tr[rt].l].siz;
			tr[tr[rt].l].b=0;
			tr[tr[rt].l].a1=0;
			tr[tr[rt].l].b1=tr[tr[rt].l].siz;
			
			tr[tr[rt].r].a=tr[tr[rt].r].siz;
			tr[tr[rt].r].b=0;
			tr[tr[rt].r].a1=0;
			tr[tr[rt].r].b1=tr[tr[rt].r].siz;
		}else{
			tr[tr[rt].l].b=tr[tr[rt].l].siz;
			tr[tr[rt].l].a=0;
			tr[tr[rt].l].b1=0;
			tr[tr[rt].l].a1=tr[tr[rt].l].siz;
			
			tr[tr[rt].r].b=tr[tr[rt].r].siz;
			tr[tr[rt].r].a=0;
			tr[tr[rt].r].b1=0;
			tr[tr[rt].r].a1=tr[tr[rt].r].siz;
		}
		tr[rt].rep=0;
	}if(tr[rt].swp){
		swap(tr[rt].l,tr[rt].r);
		tr[tr[rt].l].swp^=1;
		tr[tr[rt].r].swp^=1;
		tr[rt].swp=0;
	}
}

void pushup(int rt){
	tr[rt].siz=tr[tr[rt].l].siz+tr[tr[rt].r].siz+1;
	int x=tr[tr[rt].l].b,y=tr[tr[rt].r].a;
	int x2=tr[tr[rt].l].b1,y2=tr[tr[rt].r].a1;
	if(x<y){
		tr[rt].a=tr[tr[rt].l].a-x+y;
		tr[rt].b=tr[tr[rt].r].b;
		
	}else{
		tr[rt].a=tr[tr[rt].l].a;
		tr[rt].b=x-y+tr[tr[rt].r].b;
	}
	if(x2<y2){
		tr[rt].a1=tr[tr[rt].l].a1-x2+y2;
		tr[rt].b1=tr[tr[rt].r].b1;
	}else{
		tr[rt].a1=tr[tr[rt].l].a1;
		tr[rt].b1=x2-y2+tr[tr[rt].r].b1;
	}
}

void split(int p,int k,int &x,int &y){//分裂排名前k
	if(!p){
		x=y=0;
		return ;
	}
	if(tr[tr[p].l].siz>=k){
		y=p;
		pushdown(p);
		split(tr[p].l,k,x,tr[p].l);
		pushup(p);
	}else{
		x=p;
		pushdown(p);
		k-=tr[tr[p].l].siz+1;
		split(tr[p].r,k,tr[p].r,y);
	}
}

int merge(int a,int b){
	if(!a||!b) return a+b;
	if(tr[a].key<tr[b].key){
		pushdown(a);
		tr[a].r=merge(tr[a].r,b);
		pushup(a);return a;
	}else{
		pushdown(b);
		tr[b].l=merge(a,tr[b].l);
		pushup(b);return b;
	}
}

int main(){
	int n,q;
	cin >> n >> q;
	char p;
	for(int i=1;i<=n;i++){
		cin >> p;
		if(p=='('){
			root=merge(root,newnode(0,1));
		}else{
			root=merge(root,newnode(1,0));
		}
	}
	while(q--){
		string s;
		cin >> s;
		if(s=="Swap"){
			int a,b;
			cin >> a >> b;
			int x,y,z;
			split(root,b,x,z);
			split(x,a-1,x,y);
			tr[y].swp=1;
			root=merge(merge(x,y),z);
		}else if(s=="Invert"){
			int a,b;
			cin >> a >> b;
			int x,y,z;
			split(root,b,x,z);
			split(x,a-1,x,y);
			tr[y].inv=1;
			root=merge(merge(x,y),z);
		}else if(s=="Replace"){
			int a,b;char c;
			cin >> a >> b>> c;
			int x,y,z;
			split(root,b,x,z);
			split(x,a-1,x,y);
			if(c=='('){
				tr[y].rep=1;
			}else{
				tr[y].rep=2;
			}
			root=merge(merge(x,y),z);
		}else{
			int a,b;
			cin >> a >> b;
			int x,y,z;
			split(root,b,x,z);
			split(x,a-1,x,y);
			int p=tr[y].a,q=tr[y].b;
			cout << p/2+p%2+q/2+q%2 << endl;
			root=merge(merge(x,y),z);
		}
	}
}
2024/3/29 00:31
加载中...