P3797 妖梦斩木棒 线段树区间合并
Posted 昵称很长很长真是太好了
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3797 妖梦斩木棒 线段树区间合并相关的知识,希望对你有一定的参考价值。
题意:
1 x C 将第x个小段的木棒替换成C型,C只会是’X’,’(‘,’)’中的一种
2 l r 询问妖梦从第l段到第r段之间(含l,r),有多少个完整的木棒
完整的木棒左右两端必须分别为’(‘和’)’,并且中间要么什么都没有,要么只能有’X’。
题解:
典型的线段树维护区间合并问题 (特别注意query中的合并)
开三个数组,ls代表左端是否拥有右括号,rs代表右端是否有左括号,ishave用来代表区间中是否有括号。
代码:
#include<bits/stdc++.h>
#define endl '\\n'
using namespace std;
const int maxn=1e6+10;
int sum[maxn];
int ls[maxn],rs[maxn];
int ishave[maxn];
void push_up(int node)
sum[node]=sum[node<<1]+sum[node<<1|1];
if(ls[node<<1|1]==1&&rs[node<<1]==1)
sum[node]++;
ishave[node]=ishave[node<<1]|ishave[node<<1|1];
if((ls[node<<1|1]&&!ishave[node<<1])||ls[node<<1]) ls[node]=1;
else ls[node]=0;
if((rs[node<<1]&&!ishave[node<<1|1])||rs[node<<1|1]) rs[node]=1;
else rs[node]=0;
void update(int node,int start,int ends,int pos,char c)
if(start==ends)
if(c=='(') rs[node]=1,ls[node]=0,ishave[node]=1;
if(c==')') ls[node]=1,rs[node]=0,ishave[node]=1;
if(c=='X') ls[node]=rs[node]=ishave[node]=0;
return ;
int mid=(start+ends)>>1;
if(pos<=mid) update(node<<1,start,mid,pos,c);
else update(node<<1|1,mid+1,ends,pos,c);
push_up(node);
int query(int node,int start,int ends,int l,int r,int &L,int &R)
if(l<=start&&ends<=r)
if(rs[node]) R=1;
else R=0;
if(ls[node]) L=1;
else L=0;
return sum[node];
int mid=(start+ends)>>1;
int res=0;
int LL=-1,RR=-1,LR=-1,RL=-1;
if(l<=mid) res+=query(node<<1,start,mid,l,r,LL,LR);
if(mid<r) res+=query(node<<1|1,mid+1,ends,l,r,RL,RR);
if(RR||(LR==1&&!ishave[node<<1|1])) R=1;
else R=0;
if(LL||(!ishave[node<<1]&&RL==1)) L=1;
else L=0;
if((LR==1&&RL==1)) res++;
return res;
int main()
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
// freopen("P3797_1.in","r",stdin);
// freopen("P3797_1.out","w",stdout);
int n,m;
cin>>n>>m;
update(1,1,n,1,'(');
update(1,1,n,n,')');
while(m--)
int opt;
cin>>opt;
if(opt==1)
int x;
char c;
cin>>x>>c;
update(1,1,n,x,c);
else
int l,r;
cin>>l>>r;
int x=0,y=0;
cout<<query(1,1,n,l,r,x,y)<<endl;
以上是关于P3797 妖梦斩木棒 线段树区间合并的主要内容,如果未能解决你的问题,请参考以下文章