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;
    }
    

      

  • 相关阅读:
    网络安全分析
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1464 Function
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1014 Cantor表
    java实现 洛谷 P1540 机器
    java实现 洛谷 P1540 机器
  • 原文地址:https://www.cnblogs.com/clrs97/p/7337140.html
Copyright © 2011-2022 走看看