zoukankan      html  css  js  c++  java
  • V-Parenthesis 前缀+ZKW线段树或RMQ

    Bobo has a balanced parenthesis sequence P=p 1 p 2…p n of length n and q questions.
    The i-th question is whether P remains balanced after p ai and p bi  swapped. Note that questions are individual so that they have no affect on others.
    Parenthesis sequence S is balanced if and only if:
    1. S is empty;
    2. or there exists balanced parenthesis sequence A,B such that S=AB;
    3. or there exists balanced parenthesis sequence S' such that S=(S').


    题意就是给出一个正确配对的括号序列,问交换两个括号以后是否依旧正确配对,一般括号配对都可以使用遇到左括号加一,遇到右括号减一的方法,中间过程中不能出现负值,否则配对失败,这道题也可以这样做,先求出前缀和,如:

    编号: 1    2   3  4   5   6    7   8

             (    (    (    )    )    )    (    )

    前缀: 1   2    3  2   1   0     1  0

    有两种仍然可以配对的交换:1.当交换的两个括号相同时,2.ai是右括号,bi是左括号时,根据示例可以看出;

    唯一一种可能发生不配对的交换:ai是左括号,bi是右括号;当有右括号加入ai位置时,从ai位置到bi-1位置的前缀和全部都要减2,所以ai到bi-1区间内最小值至少为2,这样就变成了查询区间最小值问题了,可以用线段树,也可以RMQ(代码待补);因为刚刚学习线段树,又刚好听说ZKW线段树代码比较精简,所以临时现去学习了一下,结果发现好多给的示例代码都是错的。。。这个版本可能也有错,但是AC了就好。。。哈哈哈哈哈哈哈哈哈嗝。。。。

    zkw线段树:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    const int N = 100000 + 5;
    const int INF = (1<<28);
    int sum[N],T[N<<2],cnt,M;
    char ch[N];
    
    void Build(int n){
        int i;
        for(M=1;M<=n+1;M*=2);
        for(i=1+M;i<=n+M;i++) T[i] = sum[cnt++];
        for(i=M-1;i;i--) T[i]=min(T[i<<1],T[i<<1|1]);
    }
    
    void Update(int n,int V){
        for(T[n+=M]=V,n/=2;n;n/=2)
            T[n]=min(T[n<<1],T[n<<1|1]);
    }
    
    int Query(int s,int t){
        int minc=INF;
        for(s=s+M-1,t=t+M+1;s^t^1;s/=2,t/=2){
            if(~s&1) minc=min(minc,T[s^1]);
            if(t&1) minc=min(minc,T[t^1]);
        }
        return minc;
    }
    int main(){
        int n,q,a,b;
        while(scanf("%d %d",&n,&q)==2){
            scanf("%s",ch+1);
            sum[0] = 0;
            for(int i=1;i<=n;i++){
                if(ch[i]=='(') sum[i]=sum[i-1]+1;
                else sum[i]=sum[i-1]-1;
            }
            cnt = 1;
            Build(n);
            for(int i=0;i<q;i++){
                scanf("%d %d",&a,&b);
                if(a > b) swap(a,b);
                if(ch[a]==ch[b] || (ch[a]==')'&&ch[b]=='(')){ printf("Yes
    "); continue; }
                int ret = Query(a,b-1);
                printf("%s
    ",ret>=2?"Yes":"No");
            }
        }
        return 0;
    }


    RMQ:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    const int N = 100000 + 5;
    const int INF = (1<<28);
    int sum[N],dp[N][32],cnt,n;
    char ch[N];
    void RMQ_Init(){
        memset(dp,0,sizeof(dp));
        for(int i=0;i<n+1;i++) dp[i][0] = sum[i];
        for(int j=1;(1<<j)<=n+1;j++)
            for(int i=0;i+(1<<j)-1 < n+1;i++)
            dp[i][j] = min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    int RMQ(int L,int R){
        int k = 0;
        while((1<<(k+1))<=R-L+1) k++;
        return min(dp[L][k],dp[R-(1<<k)+1][k]);
    }
    int main(){
        int q,a,b;
        while(scanf("%d %d",&n,&q)==2){
            scanf("%s",ch+1);
            sum[0] = 0;
            for(int i=1;i<=n;i++){
                if(ch[i]=='(') sum[i]=sum[i-1]+1;
                else sum[i]=sum[i-1]-1;
            }
            cnt = 1;
            RMQ_Init();
            for(int i=0;i<q;i++){
                scanf("%d %d",&a,&b);
                if(a > b) swap(a,b);
                if(ch[a]==ch[b] || (ch[a]==')'&&ch[b]=='(')){ printf("Yes
    "); continue; }
                int ret = RMQ(a,b-1);
                printf("%s
    ",ret>=2?"Yes":"No");
            }
        }
        return 0;
    }
     


  • 相关阅读:
    setMasksToBounds
    CSRF跨站
    ORM: object relationship mapping
    orm查询
    图书管理系统(增删改)
    django图书管理半成品(MySQL)
    模板继承(练习测试)
    模板层(template)
    django命令(笔记,自己看的)
    django(注册→登录→主页)增强版
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7347672.html
Copyright © 2011-2022 走看看