-
题意:有一长度为\(n\)的括号序列,有\(q\)个询问,两种操作,1是交换\(l\)和\(r\)位置的字符,2是询问\(l\)到\(r\)的括号序列是否合法。
-
题解:先将括号序列用\(1\)和\(-1\)表示,不难发现,对于一个合法的括号序\([l,r]\),其区间和一定为0,且区间内任一位置的前缀和都不能小于\(0\),即前缀和最小值不小于\(0\),那么题目也就转化成了,求区间和以及区间最小值,这里可以用到线段树的一个小技巧,我们只用维护区间最小值,更新的时候\([l,n]\)和\([r,n]\)这样区间更新就可以维护前缀和,查询的时候判断一下两个条件是否满足即可。
-
代码:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} int n,q; char s[N]; int b[N]; struct Node{ int l,r; int mi; int tag; }tr[N<<4]; void push_up(int u){ tr[u].mi=min(tr[u<<1].mi,tr[u<<1|1].mi); } void push_down(int u){ tr[u<<1].mi+=tr[u].tag; tr[u<<1].tag+=tr[u].tag; tr[u<<1|1].mi+=tr[u].tag; tr[u<<1|1].tag+=tr[u].tag; tr[u].tag=0; } void build(int u,int l,int r){ if(l==r){ tr[u]={l,r}; return; } tr[u]={l,r}; int mid=(l+r)>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); push_up(u); } void update(int u,int L,int R,int x){ if(tr[u].l>=L && tr[u].r<=R){ tr[u].tag+=x; tr[u].mi+=x; return; } push_down(u); int mid=(tr[u].l+tr[u].r)>>1; if(L<=mid) update(u<<1,L,R,x); if(R>mid) update(u<<1|1,L,R,x); push_up(u); } int query(int u,int L,int R){ if(tr[u].l>=L && tr[u].r<=R){ return tr[u].mi; } push_down(u); int mid=(tr[u].l+tr[u].r)>>1; int res=INF; if(L<=mid) res=min(res,query(u<<1,L,R)); if(R>mid) res=min(res,query(u<<1|1,L,R)); return res; } int main() { scanf("%d %d",&n,&q); getchar(); scanf("%s",s+1); for(int i=1;i<=n;++i){ b[i]=(s[i]=='(')?1:(-1); } build(1,1,n); for(int i=1;i<=n;++i) update(1,i,n,b[i]); while(q--){ int op,l,r; scanf("%d %d %d",&op,&l,&r); if(op==1){ update(1,l,n,-b[l]); update(1,r,n,-b[r]); swap(b[l],b[r]); update(1,l,n,b[l]); update(1,r,n,b[r]); } else{ int pre; if(l==1) pre=0; else pre=query(1,l-1,l-1); if(query(1,r,r)==pre && query(1,l,r)-pre==0) puts("Yes"); else puts("No"); } } return 0; }