ShanDong Multi-University Training #5 - Virtual Judge (csgrandeur.cn)
给定一个括号串。
操作1:交换第l个和第r个位置
操作2:判断是不是正确的括号序列。
关键思维:
对于匹配问题。
第一个:数量不匹配。第二个:对于任意一个),前面必须存在没有匹配的(。这个思想也完完全全是stack写括号匹配的思路!这是匹配问题的本质。
- 要确定一件事,除了 “)(”这种类型的或者是“(”和“)”数量不匹配以外,其他的都是正确的。
- 1、我们需要维护的信息是哪些呢?对于当前的序列你要保证不能出现第一种情况。记录对于当前序列的需要匹配的左括号为kl,又括号为kr。这个信息是可以传上来的。我们可以想象,当最后两个序列合并的时候,必须满足r.kl == l.kr && l.kr = r.kl = 0才算匹配成功。2、也可以将“)”视为-1,“(”视为1,和上面想法差不多,但有数字的妙用,用正负1来解决这种匹配的问题,再结合sum,差分等。根据上面的关键思维,我们就能得出,需要维护前缀和的最小值,最小值必须>=0(准确说=0,因为最后要=0),前缀和一旦小于0,那么一定是)比(多,就能对应上第二种情况了。除了这样想,也可以想题目要求两个括号相等,如果(多的话,最后的sum一定>0;如果)多的话怎么办呢?对于stack来说不能为空,对于前缀和来说就是前缀和的最小值一定不能为负。所以此题维护的是一个sum,一个lmax
法1:直观简单的记录左右需要匹配的( 和 )
#include <bits/stdc++.h>
#define rep(a,b,c) for(int a=b;a<=c;a++)
#define dec(a,b,c) for(int a=b;a>=c;a--)
#define x first
#define y second
#define pb push_back
#define LL long long
#define ios ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define INF 0x3f3f3f3f
#define PII pair<int,int>
#define pi acos(-1)
#define PIP pair<int,pair<int,int>>
using namespace std;
const int N=2e5+10;
int n,q;
char s[N];
struct Node
{
int l,r;
int kl=0,kr=0;
}tr[N*4];
void pushup(int u)
{
tr[u].kl=max(0,tr[u<<1].kl-tr[u<<1|1].kr)+tr[u<<1|1].kl;
tr[u].kr=max(0,tr[u<<1|1].kr-tr[u<<1].kl)+tr[u<<1].kr;
}
void build(int u,int l,int r)
{
tr[u].l=l,tr[u].r=r;
if(l==r){
if(s[l]=='(')
tr[u].kl++;
else tr[u].kr++;
return;
}
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
Node num(Node l,Node r){
Node m;
m.kl=max(0,l.kl-r.kr)+r.kl;
m.kr=max(0,r.kr-l.kl)+l.kr;
return m;
}
Node query(int u,int l,int r)
{
if(tr[u].l>=l&&tr[u].r<=r) return tr[u];
int mid=tr[u].l+tr[u].r>>1;
Node k;
if(l<=mid) k=query(u<<1,l,r);
if(r>mid) k=num(k,query(u<<1|1,l,r));
return k;
}
void change(int u,int k){
if(tr[u].l==tr[u].r){
if(s[tr[u].l]=='(')
tr[u].kl--,tr[u].kr++;
else tr[u].kl++,tr[u].kr--;
return;
}
int mid=tr[u].l+tr[u].r>>1;
if(k>=tr[u].l&&k<=mid)
change(u<<1,k);
else
change(u<<1|1,k);
pushup(u);
}
int main(){
ios;
cin>>n>>q>>s+1;
build(1,1,n);
while(q--){
int num,l,r;
cin>>num>>l>>r;
if(num==1){
if(s[l]==s[r])
continue;
else{
change(1,l),change(1,r);
swap(s[l],s[r]);
}
}
else{
Node k=query(1,l,r);
if(k.kl||k.kr)
cout<<"No\n";
else cout<<"Yes\n";
}
}
return 0;
}
法2:
#include<bits/stdc++.h>
#define PII pair<int,int>
#define PLL pair<long long,long long>
#define fi first
#define se second
#define endl '\n'
#define bug printf("bug\n");
using namespace std;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
const long long LNF=0x3f3f3f3f3f3f3f3f;
const long long mod=1e9+7;
struct node{
long long l,r,sum,minn;
}tr[N<<2];
int n,m,cnt=1,last=0;
char s[N];
int st[N];
void pushup(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
tr[u].minn=min(tr[u<<1].minn,tr[u<<1].sum+tr[u<<1|1].minn);
}
void bulid(int u,int l,int r){
if(l==r){
tr[u]={l,r,st[l],st[l]};
printf("%d %d %d %d\n",l,r,tr[u].sum,tr[u].minn);
}
else{
tr[u]={l,r,0,LNF};
int mid=(tr[u].l+tr[u].r)>>1;
bulid(u<<1,l,mid); bulid(u<<1|1,mid+1,r);
pushup(u);
//printf("%d %d %d %d\n",l,r,tr[u].sum,tr[u].minn);
}
}
void update(int u,int pos,int val){
if(tr[u].l==tr[u].r){
tr[u].sum=tr[u].minn=val;
}
else{
int mid=(tr[u].l+tr[u].r)>>1;
if(pos<=mid) update(u<<1,pos,val);
if(pos>mid) update(u<<1|1,pos,val);
pushup(u);
}
}
PII query(int u,int l,int r){
if(l<=tr[u].l&&r>=tr[u].r){
//printf("1 %d %d %d %d\n",tr[u].l,tr[u].r,tr[u].sum,tr[u].minn);
return {tr[u].sum,tr[u].minn};
}
PII ls,rs;
int mid=(tr[u].l+tr[u].r)>>1;
if(l<=mid) ls=query(u<<1,l,r);
if(r>mid) rs=query(u<<1|1,l,r);
//printf("ls=%d %d")
//printf("2 %d %d %d %d\n",tr[u].l,tr[u].r,ls.sum+rs.sum,min(ls.minn,ls.sum+rs.minn));
return {ls.fi+rs.fi,min(ls.se,ls.fi+rs.se)};
}
int main(){
scanf("%d %d",&n,&m);
scanf("%s",s+1);
for(int i=1;i<=n;i++){
if(s[i]=='(') st[i]=1;
else st[i]=-1;
}
//for(int i=1;i<=n;i++) printf("%d ",st[i]); puts("");
bulid(1,1,n);
while(m--){
int a,b,c; scanf("%d %d %d",&a,&b,&c);
if(a==1){
swap(st[b],st[c]);
update(1,b,st[b]); update(1,c,st[c]);
}
else{
PII res=query(1,b,c);
//printf("%d %d\n",res.sum,res.minn);
if(res.fi==0&&res.se>=0) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}