平衡树题

P4036 [JSOI2008] 火星人

用平衡树维护:

在位置 \(x\) 后插入一个字符。

修改位置 \(x\) 的字符。

查询区间公共前缀长度可用 hash 维护前缀,二分长度,判断 hash 值是否相等。

P3215 [HNOI2011] 括号修复 / [JSOI2011] 括号序列

lxl 大佬做法。

先看查询操作,对于任意序列 ))()()((,其中已经匹配成功的不需要改,剩下的为 ))((,发现序列长度为偶数时,隔一个改一个,只需改 \((a+b)/2\) 个,长度为奇数时还需额外改一个答案为 \((a+b)/2+1\)

\(a\) 为左边右括号数量,\(b\)为右边左括号数量。

一操作:区间覆盖,一个长度为 \(len\) 的序列全部修改为右括号,那 \(a=0,b=len\)

二操作:区间翻转,因为维护的状态只有翻转和没翻转两种状态,可以同时维护这两个状态,在进行区间翻转操作时交换值。

三操作:区间反转,同样道理也不断维护反转和没反转的状态。

可以想到要先区间反转,再区间翻转,再区间覆盖。

https://www.cnblogs.com/laijinyi/p/18449771

#include <bits/stdc++.h>
#define ll long long
#define int ll
#define ls a[p].l
#define rs a[p].r
#define re register
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
#define lb(x) x&(-x);
using namespace std;
const int N=2e5+10;
const int M=8e6+10;
const int mod=1e9+7;
mt19937 rnd(251);
int n=0;
int root=0;
struct node{
int l,r;
int siz;
int rnd;
int tag1;//覆盖
int tag2;//翻转
int tag3;//反转
int v1,v2;//该点类型
int vi1,vi2;//反转
int x1,z1;//未动
int x2,z2;//翻转后
int x3,z3;//反转后
int x4,z4;//反转翻转后
}a[N];
void swp(int y){
swap(a[y].x1,a[y].x2);
swap(a[y].z1,a[y].z2);
swap(a[y].x3,a[y].x4);
swap(a[y].z3,a[y].z4);
swap(a[y].l,a[y].r);
a[y].tag2^=1;
}
void replace(int y,int k){
a[y].tag1=k;a[y].tag3=0;
if(k==1){
a[y].v1=1;
a[y].vi2=1;
a[y].x1=a[y].siz;
a[y].x2=a[y].siz;
a[y].z3=a[y].siz;
a[y].z4=a[y].siz;
a[y].v2=0;
a[y].vi1=0;
a[y].z1=0;
a[y].z2=0;
a[y].x3=0;
a[y].x4=0;
}
else{
a[y].v1=0;
a[y].vi2=0;
a[y].x1=0;
a[y].x2=0;
a[y].z3=0;
a[y].z4=0;
a[y].v2=1;
a[y].vi1=1;
a[y].z1=a[y].siz;
a[y].z2=a[y].siz;
a[y].x3=a[y].siz;
a[y].x4=a[y].siz;
}
}
void invert(int y){
swap(a[y].x1,a[y].x3);
swap(a[y].z1,a[y].z3);
swap(a[y].x2,a[y].x4);
swap(a[y].z2,a[y].z4);
swap(a[y].v1,a[y].vi1);
swap(a[y].v2,a[y].vi2);
a[y].tag3^=1;
}
void pushdown(int p){
if(a[p].tag1){
replace(ls,a[p].tag1);
replace(rs,a[p].tag1);
a[p].tag1=0;
}
if(a[p].tag2){
swp(ls);
swp(rs);
a[p].tag2=0;
}
if(a[p].tag3){
invert(ls);
invert(rs);
a[p].tag3=0;
}
}
void pushup(int p){
a[p].siz=a[ls].siz+a[rs].siz+1;
a[p].x1=a[ls].x1+max(0ll,a[p].v1-a[ls].z1);
a[p].z1=a[p].v2+max(0ll,a[ls].z1-a[p].v1);
a[p].x1=a[p].x1+max(0ll,a[rs].x1-a[p].z1);
a[p].z1=a[rs].z1+max(0ll,a[p].z1-a[rs].x1);
a[p].x3=a[ls].x3+max(0ll,a[p].vi1-a[ls].z3);
a[p].z3=a[p].vi2+max(0ll,a[ls].z3-a[p].vi1);
a[p].x3=a[p].x3+max(0ll,a[rs].x3-a[p].z3);
a[p].z3=a[rs].z3+max(0ll,a[p].z3-a[rs].x3);
a[p].x2=a[rs].x2+max(0ll,a[p].v1-a[rs].z2);
a[p].z2=a[p].v2+max(0ll,a[rs].z2-a[p].v1);
a[p].x2=a[p].x2+max(0ll,a[ls].x2-a[p].z2);
a[p].z2=a[ls].z2+max(0ll,a[p].z2-a[ls].x2);
a[p].x4=a[rs].x4+max(0ll,a[p].vi1-a[rs].z4);
a[p].z4=a[p].vi2+max(0ll,a[rs].z4-a[p].vi1);
a[p].x4=a[p].x4+max(0ll,a[ls].x4-a[p].z4);
a[p].z4=a[ls].z4+max(0ll,a[p].z4-a[ls].x4);
}
void split(int p,int k,int &x,int &y){
if(!p){
x=y=0;
return;
}
pushdown(p);
if(a[ls].siz<k){
x=p;
k-=a[ls].siz+1;
split(rs,k,rs,y);
}
else{
y=p;
split(ls,k,x,ls);
}
pushup(p);
}
int merge(int x,int y){
if(!x||!y){
return x|y;
}
pushdown(x);
pushdown(y);
if(a[x].rnd<a[y].rnd){
a[x].r=merge(a[x].r,y);
pushup(x);
return x;
}
else{
a[y].l=merge(x,a[y].l);
pushup(y);
return y;
}
}
int newnode(int v){
a[++n].rnd=rnd();
a[n].siz=1;
if(v==1){
a[n].v1=1;
a[n].vi2=1;
a[n].x1=1;
a[n].x2=1;
a[n].z3=1;
a[n].z4=1;
}
else{
a[n].v2=1;
a[n].vi1=1;
a[n].z1=1;
a[n].z2=1;
a[n].x3=1;
a[n].x4=1;
}
return n;
}
int F(int x){
return x / 2 + (x % 2 == 1);
}
signed main(){
// freopen("a.in","r",stdin);
ios::sync_with_stdio(0);
cin.tie(nullptr);
int len,m;
string s;
cin>>len>>m>>s;
for(int i=0;i<len;i++){
int k=2;
if(s[i]==')'){
k=1;
}
root=merge(root,newnode(k));
}
for(int i=1;i<=m;i++){
int l,r;
string op;
cin>>op>>l>>r;
int x,y,z;
split(root,l-1,x,y);
split(y,r-l+1,y,z);
if(op[0]=='Q'){
cout<<F(a[y].x1)+F(a[y].z1)<<"\n";
}
else if(op[0]=='R'){
char c;
cin>>c;
int k=2;
if(c==')'){
k=1;
}
replace(y,k);
}
else if(op[0]=='I'){
invert(y);
}
else{
swp(y);
}
root=merge(merge(x,y),z);
}
return 0;
}
posted @   sad_lin  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示