AtCoder-abc350_f 题解

原题链接

题意简述

给定一个字符串 \(S\),对于每个匹配的括号,将括号内的字符左右翻转并大小写反转,然后删除括号。输出最后的序列。

思路

本题为文艺平衡树的模板题。扫一遍字符串进行括号匹配,每次把最内层的括号进行操作。最后遍历一遍平衡树,将不为括号字符的字符输出。

FHQ_Treap 的常数太大,这里使用 Splay。

代码

#include<bits/stdc++.h>
#define UP(i,a,b) for(i=a;i<=(b);++i)
#define DN(i,a,b) for(i=a;i>=(b);--i)
#define up(i,a,b) for(i=a;i<(b);++i)
#define dn(i,a,b) for(i=a;i>(b);--i)
#define pa make_pair
typedef long long ll;
using namespace std;
void rdc(char &c){for(c=getchar();c==' '||c=='\r'||c=='\n';c=getchar());}

const int N=5e5+5;
char a[N];
int len,sta[N],*top;
/*sta和top用来括号匹配*/
struct node{
	bool lz,ch;
	/*lz为Lazy-Tag,ch为最后是否反转大小写*/
	int sz,vl;
	node *ls,*rs,*fa;
}t[N],*root,*tot;

void init_node(node *u,char c){
	u->lz=u->ch=false;
	u->sz=1;
	u->vl=c;
	u->ls=u->rs=u->fa=t;
}
void push_up(node *u){
	u->sz=u->ls->sz+u->rs->sz+1;
}
void tag(node *u){
	/*给子树打Lazy-Tag*/
	if(u!=t){
		swap(u->ls,u->rs);
		u->ch^=true;
		u->lz^=true;
	}
}
void push_down(node *u){
	/*下传标记*/
	if(u->lz){
		tag(u->ls);
		tag(u->rs);
		u->lz=false;
	}
}
bool ls(node *u){
	return u->fa->ls==u;
}
void rtt(node *u){
	/*Splay旋转*/
	node *f=u->fa,*g=f->fa;
	if(ls(u)){
		f->ls=u->rs;
		if(f->ls!=t){
			f->ls->fa=f;
		}
		u->rs=f;
	}else{
		f->rs=u->ls;
		if(f->rs!=t){
			f->rs->fa=f;
		}
		u->ls=f;
	}
	if(g!=t){
		ls(f)?g->ls=u:g->rs=u;
	}else{
		root=u;
	}
	f->fa=u;u->fa=g;
	push_up(f);push_up(u);
}
void splay(node *u,node *p){
	node *f,*g;
	while(u->fa!=p){
		f=u->fa;g=f->fa;
		if(g!=p){
			rtt(ls(u)^ls(f)?u:f);
		}
		rtt(u);
	}
}
node* fd(int k){
	node *u=root;
	/*找结点时要下传标记*/
	push_down(u);
	while(u->ls->sz+1!=k){
		if(k<u->ls->sz+1){
			u=u->ls;
		}else{
			k-=u->ls->sz+1;
			u=u->rs;
		}
		push_down(u);
	}
	return u;
}
node* build(node *f,int l,int r){
	/*对字符串的[l,r]建树,返回树根*/
	if(l>r){
		return t;
	}
	int mid=(l+r)>>1;
	node *u=++tot;
	init_node(u,a[mid]);
	u->fa=f;
	u->ls=build(u,l,mid-1);
	u->rs=build(u,mid+1,r);
	push_up(u);
	return u;
}
void rev(int l,int r){
	/*翻转并反转区间[l,r]*/
	node *x=fd(l),*y=fd(r+2);
	splay(x,t);
	splay(y,x);
	tag(y->ls);
}
void tra(node *u=root){
	/*遍历平衡树*/
	if(u!=t){
		push_down(u);
		tra(u->ls);
		if(u->vl!='('&&u->vl!=')'){
			/*不是括号时就输出*/
			if(u->ch){
				if(u->vl>='a'&&u->vl<='z'){
					u->vl-=32;
				}else{
					u->vl+=32;
				}
			}
			printf("%c",u->vl);
		}
		tra(u->rs);
	}
	if(u==root){
		printf("\n");
	}
}
void init(){
	init_node(t,'(');t->sz=0;
	init_node(t+1,'(');t[1].rs=t+2;t[1].sz=2;
	init_node(t+2,'(');t[2].fa=t+1;
	/*都初始化为'(',这样在遍历的时候就不输出多余字符了*/
	root=t+1;tot=t+2;top=sta;
}
int main(){
	int i;
	scanf("%s",a+1);
	len=strlen(a+1);
	init();
	t[2].ls=build(t+2,1,len);
	push_up(t+2);push_up(t+1);
	UP(i,1,len){
		if(a[i]=='('){
			++top;*top=i;
		}else if(a[i]==')'){
			/*括号匹配成功,进行翻转*/
			rev(*top,i);
			--top;
		}
	}
	tra();
	return 0;
}
posted @ 2024-04-29 20:54  lrx139  阅读(24)  评论(0编辑  收藏  举报