1 条题解
-
0
自动搬运
来自洛谷,原作者为

Wf_yjqd
哀酱永远的神/tyt /se /qq!!!搬运于
2025-08-24 22:42:14,当前版本为作者最后更新于2023-06-02 21:09:34,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
比较基础的线段树板子。
若用 表示左括号, 表示右括号,求原串的前缀和 ,考虑 为合法括号序列的条件:
1.。
2.对于任意 满足 ,有 。
考虑式二可以用区间最小值维护,且满足单调性,于是想到线段树 二分。
满足式二以后,只要找到解集中最右一个满足式一的即可。
如果 且 ,则 。
因此式一也满足单调性,这样先在 向右二分式二,再在式二最大取值向左二分式一,就可以处理询问了。
那么,如何处理修改操作呢?
考虑如果要把一个区间 取反,完全可以分成 和 分别取反。
这样就可以分成两个左端点为 的区间,于是可以用上面的前缀和维护了。
具体来说,将 取反的代价为:
全取相反数, 全加上 。
前者影响了最小值,所以再维护一个最大值,每次先交换最大和最小值再取反。
后者中,单点查询 ,然后用懒惰标记处理区间加就行。
总体复杂度 。
码量还行吧(可能线段树本身长),基本就板子。
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+84; const int maxt=5e6+84; int n,m,op,x,y,ans,slast,qzh[maxn]; char s[maxn]; struct Point{ int l,r,miin,maax,lazy_swap,lazy_add; }; struct Tree{ Point T[maxt]; inline void pushup(int x){ T[x].maax=max(T[x<<1].maax,T[x<<1|1].maax); T[x].miin=min(T[x<<1].miin,T[x<<1|1].miin); return ; } inline void swp(int x){ swap(T[x].maax,T[x].miin); T[x].maax*=-1; T[x].miin*=-1; T[x].lazy_add*=-1; T[x].lazy_swap^=1; return ; } inline void addd(int x,int val){ T[x].miin+=val; T[x].maax+=val; T[x].lazy_add+=val; return ; } inline void pushdown(int x){ if(T[x].lazy_swap){ swp(x<<1); swp(x<<1|1); T[x].lazy_swap=0; } if(T[x].lazy_add){ addd(x<<1,T[x].lazy_add); addd(x<<1|1,T[x].lazy_add); T[x].lazy_add=0; } return ; } inline void init(int id,int l,int r){ T[id].l=l; T[id].r=r; if(l==r){ T[id].maax=T[id].miin=qzh[l]; return ; } int mid=l+r>>1; init(id<<1,l,mid); init(id<<1|1,mid+1,r); pushup(id); return ; } inline void add(int id,int l,int r,int val){ if(l<=T[id].l&&T[id].r<=r){ addd(id,val); return ; } pushdown(id); int mid=T[id].l+T[id].r>>1; if(l<=mid) add(id<<1,l,r,val); if(mid<r) add(id<<1|1,l,r,val); pushup(id); return ; } inline void swapp(int id,int l,int r){ if(l<=T[id].l&&T[id].r<=r){ swp(id); return ; } pushdown(id); int mid=T[id].l+T[id].r>>1; if(l<=mid) swapp(id<<1,l,r); if(mid<r) swapp(id<<1|1,l,r); pushup(id); return ; } inline int query_p(int id,int pos){ if(!pos) return 0; if(T[id].l==T[id].r) return T[id].maax; pushdown(id); int mid=T[id].l+T[id].r>>1; if(pos<=mid) return query_p(id<<1,pos); return query_p(id<<1|1,pos); } inline void modify(int x){ if(!x) return ; if(x<n) add(1,x+1,n,-query_p(1,x)*2); swapp(1,1,x); return ; } inline int bsy(int id,int x,int val){ if(T[id].l==T[id].r) return T[id].l; pushdown(id); int anss=n+1,mid=T[id].l+T[id].r>>1; if(T[id<<1].miin<val&&x<=mid) anss=bsy(id<<1,x,val); if(anss!=n+1) return anss; if(T[id<<1|1].miin<val) anss=bsy(id<<1|1,x,val); return anss; } inline int bsz(int id,int x,int val){ if(T[id].l==T[id].r) return T[id].l; pushdown(id); int anss=-168,mid=T[id].l+T[id].r>>1; if(T[id<<1|1].miin<val&&x>mid) anss=bsz(id<<1|1,x,val); if(anss>0) return anss; if(T[id].miin<val) anss=bsz(id<<1,x,val); return anss; } inline int anser(int x){ slast=query_p(1,x-1); ans=bsz(1,bsy(1,x,slast)-1,slast+1); return ans>x?ans:0; } }Sherry; inline int mp(char c){ return c=='('?1:-1; } int main(){ scanf("%d%d",&n,&m); scanf("%s",s+1); for(int i=1;i<=n;i++) qzh[i]=qzh[i-1]+mp(s[i]); Sherry.init(1,1,n); while(m--){ scanf("%d%d",&op,&x); if(op==2){ printf("%d Sherry\n",Sherry.anser(x)); continue; } scanf("%d",&y); Sherry.modify(y); Sherry.modify(x-1); } return 0; }
- 1
信息
- ID
- 7943
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者