zoukankan      html  css  js  c++  java
  • csu 1809 Parenthesis(线段树)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+5;
    char s[maxn];
    int  pre[maxn],Min[maxn<<2];
    int n,q,u,v;
    /*
    	给一个长度为n(<=1e5)的只有()的匹配字符串,q(<=1e5)次询问
    	每次询问在原串上交换两个字符,问交换之后是否还是合法子串
    	如果把(值为1,)值为-1,那么一个区间前缀和不存在<0,并且
    	最终的和为0,肯定就是一个匹配字符串
    	那么交换的两个字符是相同的,肯定是合法的
    	如果交换的是 )(,那么肯定也是合法的
    	如果交换的是(),那么就要考虑[l,r)之间在交换后是否会产生
    	负数,交换的结果是,[l,r)都会-2,那么求[l,r)之间的最小值
    	写个线段树就好了
    */
    
    void build(int rt,int l,int r){
    	if(l==r){
    		Min[rt]=pre[l];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(rt<<1,l,mid);
    	build(rt<<1|1,mid+1,r);
    	Min[rt]=min(Min[rt<<1],Min[rt<<1|1]);
    }
    
    int query(int rt,int l,int r,int ql,int qr){
    	if(ql<=l&&qr>=r)return Min[rt];
    	
    	int mid=(l+r)>>1;
    	int res=INT_MAX;
    	if(ql<=mid)res=min(res,query(rt<<1,l,mid,ql,qr));
    	if(qr>mid)res=min(res,query(rt<<1|1,mid+1,r,ql,qr));
    	return res;
    }
    
    int main(){
    	int n,q,u,v;
    	while(~scanf("%d%d",&n,&q)){
    		getchar();gets(s);
    		for(int i=1;i<=n;i++){
    			if(s[i-1]=='(')pre[i]=1;
    			else pre[i]=-1;
    			pre[i]+=pre[i-1];
    		}
    		build(1,1,n);
    		
    		while(q--){
    			scanf("%d%d",&u,&v);
    			if(u>v)swap(u,v);
    			if(s[u-1]==s[v-1])puts("Yes");
    			else if(s[v-1]=='(')puts("Yes");
    			else{
    				int a=query(1,1,n,u,v-1);
    				if(a>1)puts("Yes");
    				else puts("No");
    			}
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    🍖名称空间与作用域
    🍖文件打开模式 "t"
    🍖函数参数
    【转】LINQ中的Aggregate语法
    【转】c#中string.trimstart() 和string.trimend() 的用法
    1094 和为k的连续区间(暴力)
    1095 Anigram单词
    1031 骨牌覆盖 (斐波拉契数列)
    最长公共子序列(模板 LCSL)
    1092 回文字符串(LCSL_DP)
  • 原文地址:https://www.cnblogs.com/jihe/p/6678156.html
Copyright © 2011-2022 走看看