列表

详情


NC54760. 完美世界

描述

Bob有一个长度为 n 的括号序列 S( 仅含有 '(' 和 ')'),有一天他对该序列作出m次如下操作:

1. c l r 将下标为l,r的括号取反,即 '(' 转换成 ')' ,')' 转换成 '(' ,并回答当前**S是否完全匹配**.

2. q l r 回答**区间[l,r]的括号序列是否完全匹配**.

3. t l r 将下标为 l 和 r 的括号进行交换,并回答当前**S是否完全匹配**.

定义一个括号序列 S 是完全匹配的当且仅当:

1. S 为空 ;

2. 或存在完全匹配的括号序列A,B,且S = AB

3.或存在完全匹配的括号序列 S' ,且 S = ( S' )

注意上述定义其实合法括号序列的递归定义,若不理解可以无视,完全匹配的定义是只要当前询问的括号**合法**即可,即不存在不能匹配的左括号与右括号。

但这个问题实在是太难了,Bob无法解决,所以他把这个问题转交给你。

,,

输入描述

第一行两个整数,表示n和m

第二行输入长度为 n (保证n为偶数)的字符串 S

接下来m次询问, x l r ,x 表示进行操作的类型,l r 表示区间下标(x { 'c','q','t' } )

输出描述

若当前所需询问的括号序列合法,则输出"YES",反之输出"NO"(输出时不带引号).

示例1

输入:

4 3
())(
c 3 4
t 3 4
q 1 2

输出:

YES 
NO
YES

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Java(javac 1.8) 解法, 执行用时: 1104ms, 内存消耗: 75124K, 提交时间: 2019-12-07 23:41:34

import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Random;
import java.util.StringTokenizer;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) throws IOException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader sc = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        Task solver = new Task();
        solver.solve(1, sc, out);
        out.close();
    }

    static class Task {
        public void solve(int testNumber, InputReader sx, PrintWriter outs) throws IOException {
        /*	File file_in=new File("C:\\Users\\Garett\\Desktop\\题目\\完美世界\\数据","20.in");
    	    FileReader in=new FileReader(file_in);
    	    BufferedReader sc=new BufferedReader(in);
    	    File file_out=new File("C:\\Users\\Garett\\Desktop\\题目\\完美世界\\数据","20.out");
    		FileWriter out=new FileWriter(file_out);
    		BufferedWriter puts=new BufferedWriter(out);
    	    
    	    String[] temp=sc.readLine().split(" ");
            int n=Integer.parseInt(temp[0]);
            int m=Integer.parseInt(temp[1]);
            char[] buf=(" "+sc.readLine()).toCharArray();*/
        	int n=sx.nextInt();
        	int m=sx.nextInt();
        	char[] buf=(" "+sx.next()).toCharArray();
            int[] cur=new int[buf.length];
            for(int i=1;i<buf.length;i++) {
            	if(buf[i]=='(')
            		cur[i]=1;
            	
            	else
            		cur[i]=0;
            }
            SegmentTree sgt=new SegmentTree(n,buf);
            sgt.build(1, 1, n);
            boolean flag=false;
            while(m-->0) {
            	/*temp=sc.readLine().split(" ");
            	char opt=temp[0].charAt(0);
            	int l=Integer.parseInt(temp[1]);
            	int r=Integer.parseInt(temp[2]);*/
            	char opt=sx.next().charAt(0);
            	int l=sx.nextInt();
            	int r=sx.nextInt();
            	
            	if(opt=='c') {
            		cur[l]^=1;
            		cur[r]^=1;
            		sgt.change(1, l);
            		sgt.change(1, r);
            		if(sgt.t[1].l_val==0&&sgt.t[1].r_val==0) {
            		//	puts.println("YES");
            			outs.println("YES");
            			flag=true;
            		}
            		else
            			//puts.println("NO");
            			outs.println("NO");
            	}
            	if(opt=='q') {
            		SegmentTree.Node ans=sgt.ask(1, l, r);
            		if(ans.l_val==0&&ans.r_val==0) {
            			//puts.println("YES");
            			outs.println("YES");
            			flag=true;
            		}
            		else
            			//puts.println("NO");
            			outs.println("NO");
            	}
            	if(opt=='t') {
            		int temp=cur[l];
            	    cur[l]=cur[r];
            	    cur[r]=temp;
            		sgt.change(1, l ,cur[l]);
            		sgt.change(1, r ,cur[r]);
            		
            		if(sgt.t[1].l_val==0&&sgt.t[1].r_val==0) {
            		//	puts.println("YES");
            			outs.println("YES");
            			flag=true;
            		}
            		else
            			//puts.println("NO");
            			outs.println("NO");
            	}
            //	puts.newLine();
            }
            /*System.out.println(flag);
            puts.close();
        	sc.close();*/
        }
    }
    
    public static class SegmentTree{
    	class Node{
    		int l;
    		int r;
    	    int l_val;
    	    int r_val;
    	    
    	    public Node(int l,int r) {
    	    	this.l=l;
    	    	this.r=r;
    	    }
    	    
    	    public Node(int l,int r,int l_val,int r_val) {
    	    	this.l=l;
    	    	this.r=r;
    	    	this.l_val=l_val;
    	    	this.r_val=r_val;
    	    }
    	}
    	public char[] buf;
        public Node[] t;
        
        public SegmentTree(int n,char[] buf) {
        	this.buf=buf;
        	this.t=new Node[(n+10)<<2];
        }
        
        public void pushUp(int p) {
        	int temp1=t[p*2].l_val;
    		int temp2=t[p*2+1].r_val;

    		t[p].l_val=Math.max(0, temp1-temp2)+t[p*2+1].l_val;
    		t[p].r_val=t[p*2].r_val+Math.max(0, temp2-temp1);
        }
        
        public void build(int p,int l,int r) {
        	t[p]=new Node(l,r);
        	if(l==r) {
        		if(buf[l]=='(')
        			t[p].l_val=1;
        		else
        			t[p].r_val=1;
        		return ;
        	}
        	int mid=(l+r)>>1;
        	build(p*2,l,mid);
        	build(p*2+1,mid+1,r);
        	pushUp(p);
        }
        
        public void change(int p,int index,int val) {    //1置为左括号   0置为括号
        	if(t[p].l==t[p].r) {
        		if(val==1) {
        			t[p].l_val=1;
        			t[p].r_val=0;
        		}
        		else {
        			t[p].l_val=0;
        			t[p].r_val=1;
        		}
        		return  ;
        	}
        	int mid=(t[p].l+t[p].r)>>1;
        	if(index<=mid)
        		change(p*2,index,val);
        	else
        		change(p*2+1,index,val);
        	pushUp(p);
        }
        
        public void change(int p,int index) {
        	if(t[p].l==t[p].r) {
        		if(t[p].l_val==1) {
        			t[p].l_val=0;
        			t[p].r_val=1;
        		}
        		else {
        			t[p].l_val=1;
        			t[p].r_val=0;
        		}
        		return ;
        	}
        	int mid=(t[p].l+t[p].r)>>1;
        	if(index<=mid)
        		change(p*2,index);
        	else
        		change(p*2+1,index);
        	pushUp(p);
        }
        
        public Node ask(int p,int l,int r) {
        	if(t[p].l>=l&&t[p].r<=r)
        		return t[p];
        	Node res1=null;
        	Node res2=null;
        	int mid=(t[p].l+t[p].r)>>1;
        	if(l<=mid)
        		res1=ask(p*2,l,r);
        	if(r>mid)
        		res2=ask(p*2+1,l,r);
        	if(res1==null)
        		return res2;
        	if(res2==null)
        		return res1;
        	int temp1=res1.l_val;
    		int temp2=res2.r_val;

    		int l_val=Math.max(0, temp1-temp2)+res2.l_val;
    		int r_val=res1.r_val+Math.max(0, temp2-temp1);
    		return new Node(0,0,l_val,r_val);
        }
    }

    static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;

        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }

        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}

C++14(g++5.4) 解法, 执行用时: 267ms, 内存消耗: 5372K, 提交时间: 2020-02-05 21:05:05

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + 7;
typedef long long ll;
struct node {
    int l, r, val;
    int lazy;
}t[maxn*4];
int val[maxn];
void pushup(int n) {
    t[n].val = min(t[n<<1].val, t[n<<1|1].val);
}
void pushdown(int n) {
    if(t[n].lazy) {
        int l = t[n].l, r = t[n].r;
        if(l == r) return;
        int mid = (l + r)>> 1;
        t[n<<1].val += t[n].lazy;
        t[n<<1|1].val += t[n].lazy;
        t[n<<1].lazy += t[n].lazy;
        t[n<<1|1].lazy += t[n].lazy;
        t[n].lazy = 0;
    }
}
void build(int n, int l, int r) {
    t[n].l = l;
    t[n].r = r;
    t[n].lazy = 0;
    if(l == r) {
        t[n].val = val[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(n<<1, l, mid);
    build(n<<1|1, mid + 1, r);
    pushup(n);
}
void update(int n, int L, int R, int C) {
    int l = t[n].l, r = t[n].r;
    if(L <= l && R >= r) {
        t[n].lazy += C;
        t[n].val += C;
        return;
    }
    pushdown(n);
    int mid = (l + r) >> 1;
    if(L <= mid) update(n<<1, L, R, C);
    if(R > mid) update(n<<1|1, L, R, C);
    pushup(n);
}
int query(int n, int L, int R) {
    if(L == 0 && R == 0) return 0;
    int l = t[n].l, r = t[n].r;
    if(L <= l && R >= r) {
        return t[n].val;
    }
    pushdown(n);
    int mid = (l + r) >> 1, ans = INF;
    if(L <= mid) ans = min(ans, query(n<<1, L, R));
    if(R > mid) ans = min(ans, query(n<<1|1, L, R));
    return ans;
}
int cal(int x, int y) {
    int tmp = query(1, x - 1, x - 1);
    int sum = query(1, y, y) - tmp;
    update(1, x, y, -tmp);
    int minx = query(1, x, y);
    if(minx == 0 && sum == 0) printf("YES\n");
    else printf("NO\n");
    update(1, x, y, tmp);
}
int main()
{
    int n, m;
    cin >> n >> m;
    char s[maxn];
    scanf("%s", s + 1);
    for (int i = 1; i <= n; i++) {
        if(s[i] == '(') val[i] = val[i - 1] + 1;
        else val[i] = val[i - 1] - 1;
    }
    build(1, 1, n);
    while (m--) {
        char ss[100];
        int x, y;
        scanf("%s %d %d", ss, &x, &y);
        if(ss[0] == 't') {
            if(s[x] == '(' && s[y] == ')') {
                update(1, x, y - 1, -2);
                s[y] = '(';
                s[x] = ')';
            }
            else if(s[x] == ')' && s[y] == '(') {
                update(1, x, y - 1, 2);
                s[x] = '('; s[y] = ')';
            }
            cal(1, n);
        }
        else if(ss[0] == 'c') {
            if(s[x] == ')') update(1, x, n, 2), s[x] = '(';
            else update(1, x, n, -2), s[x] = ')';
            if(s[y] == '(') update(1, y, n, -2), s[y] = ')';
            else update(1, y, n, 2), s[y] = '(';
            cal(1, n);
        }
        else if(ss[0] == 'q') {
            cal(x, y);
        }
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 157ms, 内存消耗: 4588K, 提交时间: 2019-12-07 23:41:10

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <string>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <set>
#define inf 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define inff 0x3f3f3f3f3f3f3f3f
using namespace std;

const int N=1e5+5;
int n,m;
char s[N];
int val[N],a[N<<2],lz[N<<2];

void build(int l,int r,int alt)//建树 
{
	if(l==r){
		a[alt]=val[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,alt<<1);
	build(mid+1,r,alt<<1|1);
	a[alt]=max(a[alt<<1],a[alt<<1|1]);
}

void pushDown(int alt)//向下更新 
{
	if(lz[alt]){
		a[alt<<1]+=lz[alt];
		lz[alt<<1]+=lz[alt];
		a[alt<<1|1]+=lz[alt];
		lz[alt<<1|1]+=lz[alt];
		lz[alt]=0;
	}
}

void update(int l,int r,int alt,int L,int R,int k)//区间更新 
{
	if(L<=l&&r<=R){
		a[alt]+=k;lz[alt]+=k;
		return ;
	}
	pushDown(alt);
	int mid=(l+r)>>1;
	if(L<=mid)	update(l,mid,alt<<1,L,R,k);
	if(R>mid)	update(mid+1,r,alt<<1|1,L,R,k);
	a[alt]=max(a[alt<<1],a[alt<<1|1]);
}

int queryRange(int l,int r,int alt,int L,int R)//区间查询 
{
	 if(L<=l&&r<=R){
		return a[alt];
	}
	pushDown(alt);
	int mid=(l+r)>>1,mi=-inf;
	if(L<=mid)	mi=max(mi,queryRange(l,mid,alt<<1,L,R));
	if(R>mid)	mi=max(mi,queryRange(mid+1,r,alt<<1|1,L,R));
	return mi;
}

int queryPoint(int l,int r,int alt,int x)//单点查询 
{
	if(x==0)	return 0;
	if(l==r){
		return a[alt];
	}
	pushDown(alt);
	int mid=(l+r)>>1;
	if(x<=mid)	return queryPoint(l,mid,alt<<1,x);
	else	return queryPoint(mid+1,r,alt<<1|1,x);
}

void solve(int l,int r)//判断该区间是否完全匹配 
{
	int ect=queryPoint(1,n,1,l-1);
	int sum=queryPoint(1,n,1,r)-ect;
	update(1,n,1,l,r,-ect);//区间-a[l-1],再找最小值 
	int mi=queryRange(1,n,1,l,r);
	if(mi<=0&&sum==0)	puts("YES");
	else	puts("NO");
	update(1,n,1,l,r,ect);//区间还原+a[l-1] 
}

int main()
{
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	for(int i=1;i<=n;i++){
		if(s[i]=='(')	val[i]=val[i-1]-1;
		else	val[i]=val[i-1]+1;
	}
	build(1,n,1);
	while(m--){
		char c;int l,r;getchar();
		scanf("%c %d %d",&c,&l,&r);
		if(c=='c'){
			if(s[l]=='(')	update(1,n,1,l,n,2),s[l]=')';
			else	update(1,n,1,l,n,-2),s[l]='(';
			if(s[r]=='(')	update(1,n,1,r,n,2),s[r]=')';
			else	update(1,n,1,r,n,-2),s[r]='(';
			solve(1,n);
		}else if(c=='q'){
			solve(l,r);
		}else if(c=='t'){
			//情况一
			if(s[l]=='('&&s[r]==')')	update(1,n,1,l,r-1,2);
			//情况二 
			else if(s[l]==')'&&s[r]=='(')	update(1,n,1,l,r-1,-2);
			swap(s[l],s[r]);
			solve(1,n);
		}
	}
	return 0;
}

上一题