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

    把$($看作$-1$,$)$看作$1$,设$a$为前缀和,则相当于找两个位置$x,y$使得$a[x]=a[y]$,且$a[x]$是$[x,y]$的区间最大值。

    求出询问区间的最大值$o$,然后找到$o$在该区间内最左和最右的出现位置,将其作为答案。

    那么剩下的答案只可能在$[l,o)$或$(o,r]$,以$[l,o)$为例。

    通过单调栈求出每个位置$i$往右最长延伸长度$g[i]$,使得中间$a[i]$是区间最大值,且$a[i]=a[i+g[i]]$。

    那么在$[l,o)$中,因为$o$的阻隔,必然满足$i+g[i]<o$,找到最大的即可。

    时间复杂度$O(nlog n)$。

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef pair<int,int>P;
    const int N=400010,M=1050000,inf=~0U>>1;
    int n,m,i,x,y,l,r,o,ans,a[N],q[N],t,f[N],g[N],v[M],vf[M],vg[M];P b[N];char s[N];
    inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
    inline void up(int&a,int b){a<b?(a=b):0;}
    void build(int x,int a,int b){
      if(a==b){
        v[x]=::a[a];
        vf[x]=f[a];
        vg[x]=g[a];
        return;
      }
      int mid=(a+b)>>1;
      build(x<<1,a,mid),build(x<<1|1,mid+1,b);
      v[x]=max(v[x<<1],v[x<<1|1]);
      vf[x]=max(vf[x<<1],vf[x<<1|1]);
      vg[x]=max(vg[x<<1],vg[x<<1|1]);
    }
    int ask(int x,int a,int b,int c,int d,int*v){
      if(c<=a&&b<=d)return v[x];
      int mid=(a+b)>>1,t=-inf;
      if(c<=mid)t=ask(x<<1,a,mid,c,d,v);
      if(d>mid)up(t,ask(x<<1|1,mid+1,b,c,d,v));
      return t;
    }
    int main(){
      scanf("%d%d%s",&n,&m,s+2);n++;
      for(i=2;i<=n;i++)a[i]=a[i-1]+(s[i]==')'?1:-1);
      for(i=1;i<=n;i++)b[i]=P(a[i],i);
      sort(b+1,b+n+1);
      for(q[t=0]=0,i=1;i<=n;q[++t]=i++){
        while(t&&a[i]>=a[q[t]])t--;
        f[i]=i-upper_bound(b+1,b+n+1,P(a[i],q[t]))->second;
      }
      for(q[t=0]=n+1,i=n;i;q[++t]=i--){
        while(t&&a[i]>=a[q[t]])t--;
        g[i]=(lower_bound(b+1,b+n+1,P(a[i],q[t]))-1)->second-i;
      }
      build(1,1,n);
      while(m--){
        read(x),read(y);y++;
        o=ask(1,1,n,x,y,v);
        l=lower_bound(b+1,b+n+1,P(o,x))->second;
        r=(upper_bound(b+1,b+n+1,P(o,y))-1)->second;
        ans=r-l;
        if(l>x)up(ans,ask(1,1,n,x,l-1,vg));
        if(r<y)up(ans,ask(1,1,n,r+1,y,vf));
        printf("%d
    ",ans);
      }
      return 0;
    }
    

      

  • 相关阅读:
    性能测试_LR11_数据向导
    python django部署linux服务器
    pip升级问题
    解决win10命令提示行下cnpm无反应
    adb常用命令连接设备/查看包名/查看activity
    android虚拟机sdcard操作出现mkdir failed for , Read-only file system的解决办法
    Django项目和应用创建
    mac下配置python虚拟环境
    这个是我的标题_2020_01_01_18_49_21
    这个是我的标题_2020_01_01_18_47_58
  • 原文地址:https://www.cnblogs.com/clrs97/p/7337140.html
Copyright © 2011-2022 走看看