AtCoder Beginner Contest 223 F Parenthesis Checking (线段树,前缀和)

  • 题意:有一长度为\(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;
    }
    
    
    
原文地址:https://www.cnblogs.com/lr599909928/p/15437835.html