zoukankan      html  css  js  c++  java
  • [BZOJ4964]加长的咒语

    题目大意:
      给你一个括号序列s,不一定合法。
      有q组询问,每次询问一段区间中最长的合法括号序列的长度。

    思路:
      首先我们可以将'('看做-1,将')'看做+1,那么我们可以求出这个括号序列的前缀和。
      这是一个常用的套路,不难发现对于其中一个合法的子串,其左右两端所对应的前缀和是一样的(然而反之则不一定)。
      我们不妨再预处理出每一个括号往左、往右分别能扩展到的最大距离。
      对于每一组询问,我们可以找出前缀和最大值max,显然一个合法的括号序列要么与max无关,要么刚好两端都是max。
      我们可以求出max再区间内出现的最左和最右的位置l和r,那么答案要么就是[l,r]要么就是[l,m)或(r,m]中最长的合法序列。
      这时候我们就可以对于两个区间分别求一下往左、往右能扩展的最大距离,将其作为答案即可。

     1 #include<stack>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<algorithm>
     6 inline int getint() {
     7     register char ch;
     8     while(!isdigit(ch=getchar()));
     9     register int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 const int inf=0x7fffffff,_inf=-0x80000000;
    14 const int N=400001;
    15 char s[N];
    16 int sum[N],left[N],right[N];
    17 std::stack<int> stack;
    18 std::vector<std::pair<int,int> > v;
    19 struct SegmentTree {
    20     #define _left <<1
    21     #define _right <<1|1
    22     int sum[N<<2],left[N<<2],right[N<<2];
    23     void push_up(const int &p) {
    24         sum[p]=std::max(sum[p _left],sum[p _right]);
    25         left[p]=std::max(left[p _left],left[p _right]);
    26         right[p]=std::max(right[p _left],right[p _right]);
    27     }
    28     void build(const int &p,const int &b,const int &e) {
    29         if(b==e) {
    30             sum[p]=::sum[b];
    31             left[p]=::left[b];
    32             right[p]=::right[b];
    33             return;
    34         }
    35         const int mid=(b+e)>>1;
    36         build(p _left,b,mid);
    37         build(p _right,mid+1,e);
    38         push_up(p);
    39     }
    40     int query(const int &p,const int &b,const int &e,const int &l,const int &r,const int val[]) const {
    41         if(b==l&&e==r) {
    42             return val[p];
    43         }
    44         const int mid=(b+e)>>1;
    45         int ans=_inf;
    46         if(l<=mid) ans=std::max(ans,query(p _left,b,mid,l,std::min(mid,r),val));
    47         if(r>mid) ans=std::max(ans,query(p _right,mid+1,e,std::max(mid+1,l),r,val));
    48         return ans;
    49     }
    50     #undef _left
    51     #undef _right
    52 };
    53 SegmentTree t;
    54 int main() {
    55     const int n=getint(),q=getint();
    56     scanf("%s",&s[1]);
    57     v.push_back(std::make_pair(0,0));
    58     for(register int i=1;i<=n;i++) {
    59         if(s[i]=='(') sum[i]=sum[i-1]-1;
    60         if(s[i]==')') sum[i]=sum[i-1]+1;
    61         v.push_back(std::make_pair(sum[i],i));
    62     }
    63     std::sort(v.begin(),v.end());
    64     stack.push(0);
    65     for(register int i=1;i<=n;i++) {
    66         while(stack.size()>1&&sum[stack.top()]<=sum[i]) stack.pop();
    67         left[i]=i-std::upper_bound(v.begin(),v.end(),std::make_pair(sum[i],stack.top()))->second;
    68         stack.push(i);
    69     }
    70     while(!stack.empty()) stack.pop();
    71     stack.push(n);
    72     for(register int i=n-1;~i;i--) {
    73         while(stack.size()>1&&sum[stack.top()]<=sum[i]) stack.pop();
    74         right[i]=(std::lower_bound(v.begin(),v.end(),std::make_pair(sum[i],stack.top()))-1)->second-i;
    75         stack.push(i);
    76     }
    77     t.build(1,0,n);
    78     for(register int i=0;i<q;i++) {
    79         const int b=getint()-1,e=getint();
    80         const int max=t.query(1,0,n,b,e,t.sum);
    81         const int l=std::lower_bound(v.begin(),v.end(),std::make_pair(max,b))->second;
    82         const int r=(std::upper_bound(v.begin(),v.end(),std::make_pair(max,e))-1)->second;
    83         int ans=r-l;
    84         if(b<l) ans=std::max(ans,t.query(1,0,n,b,l-1,t.right));
    85         if(r<e) ans=std::max(ans,t.query(1,0,n,r+1,e,t.left));
    86         printf("%d
    ",ans);
    87     }
    88     return 0;
    89 }
  • 相关阅读:
    Java中的 多线程编程
    Python中的字典详解
    Python中的数据类型
    Python中的字符串操作总结(Python3.6.1版本)
    R语言绘制沈阳地铁线路图
    HIVE中的order by操作
    Hive中order by,sort by,distribute by,cluster by的区别
    HDFS shell命令
    HDFS入门
    Bootstrap_Datatable Ajax请求两次问题的解决
  • 原文地址:https://www.cnblogs.com/skylee03/p/8029697.html
Copyright © 2011-2022 走看看