zoukankan      html  css  js  c++  java
  • BZOJ4384 : [POI2015]Trzy wieże

    首先只有一种字符的情况可以通过双指针在$O(n)$的时间内处理完毕。

    设$cnt[i][j]$表示前$i$个字符中$j$字符出现的次数,那么对于两个位置$j<i$:

    如果

    $cnt[i][0]-cnt[j][0] eq cnt[i][1]-cnt[j][1]$

    $cnt[i][0]-cnt[j][0] eq cnt[i][2]-cnt[j][2]$

    $cnt[i][1]-cnt[j][1] eq cnt[i][2]-cnt[j][2]$

    均成立,即

    $cnt[i][0]-cnt[i][1] eq cnt[j][0]-cnt[j][1]$

    $cnt[i][0]-cnt[i][2] eq cnt[j][0]-cnt[j][2]$

    $cnt[i][1]-cnt[i][2] eq cnt[j][1]-cnt[j][2]$

    均成立的话,那么就可以用$i-j$去更新答案。

    设$b[i]=cnt[i][0]-cnt[i][1],c[i]=cnt[i][0]-cnt[i][2],d[i]=cnt[i][1]-cnt[i][2]$。

    将所有位置按$b$从小到大排序,按$c$维护树状数组,每个区间维护$d$不同的$j$的最小值、次小值、最大值、次大值即可。

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

    #include<cstdio>
    #define N 1000010
    int n,m,i,j,D,cnt[3],col,b[N],c[N],d[N],g[N<<1],nxt[N],v[N<<1],ans;char a[N];
    struct P{
      int mi0,mi1,ma0,ma1;
      P(){mi0=mi1=ma0=ma1=-1;}
      void up(){
        if(mi0<0){mi0=ma0=j;return;}
        if(j<mi0){
          if(D!=d[mi0])mi1=mi0;
          mi0=j;
        }else if((mi1<0||j<mi1)&&D!=d[mi0])mi1=j;
        if(j>ma0){
          if(D!=d[ma0])ma1=ma0;
          ma0=j;
        }else if(j>ma1&&D!=d[ma0])ma1=j;
      }
    }T[N];
    inline int id(char x){
      if(x=='B')return 0;
      if(x=='C')return 1;
      return 2;
    }
    inline void up(int a){if(ans<a)ans=a;}
    inline void addedge(int x,int y){nxt[y]=g[x];g[x]=y;}
    inline void ins(int x){for(;x<=m;x+=x&-x)T[x].up();}
    inline void ask(int x){
      for(;x;x-=x&-x){
        P*t=T+x;
        if(~t->mi0){
          if(D!=d[t->mi0])up(j-t->mi0);else if(~t->mi1)up(j-t->mi1);
          if(D!=d[t->ma0])up(t->ma0-j);else if(~t->ma1)up(t->ma1-j);
        }
      }
    }
    inline void add(int x){if(!cnt[x])col++;cnt[x]++;}
    inline void del(int x){cnt[x]--;if(!cnt[x])col--;}
    int main(){
      scanf("%d%s",&n,a+1);
      for(i=1;i<=n;i++){
        cnt[a[i]=id(a[i])]++;
        b[i]=cnt[0]-cnt[1],c[i]=cnt[0]-cnt[2],d[i]=cnt[1]-cnt[2];
      }
      for(i=0;i<=n+n;i++)g[i]=-1;
      for(i=0;i<=n;i++)addedge(b[i]+n,i),v[c[i]+=n+1]=1;
      for(i=1;i<=n+n+1;i++)v[i]+=v[i-1];
      for(i=0;i<=n;i++){
        c[i]=v[c[i]];
        if(c[i]>m)m=c[i];
      }
      for(i=0;i<=n+n;i++){
        for(j=g[i];~j;j=nxt[j])D=d[j],ask(c[j]-1);
        for(j=g[i];~j;j=nxt[j])D=d[j],ins(c[j]);
      }
      for(i=0;i<=n;i++)c[i]=m-c[i]+1;
      for(i=1;i<=m;i++)T[i]=P();
      for(i=0;i<=n+n;i++){
        for(j=g[i];~j;j=nxt[j])D=d[j],ask(c[j]-1);
        for(j=g[i];~j;j=nxt[j])D=d[j],ins(c[j]);
      }
      for(i=0;i<3;i++)cnt[i]=0;
      for(i=j=1;i<=n;up(i-j+1),i++)for(add(a[i]);col>1;del(a[j++]));
      return printf("%d",ans),0;
    }
    

      

  • 相关阅读:
    polly异常重试、熔断
    ASP.NET Core-Linux发布部署
    ASP.NET Core-扩展Views的几种方式
    ASP.NET Core-使用AspNetCore实现AOP

    Docker-Dockerfile2
    Docker-Dockerfile1
    Docker-搭建私有仓库步骤


  • 原文地址:https://www.cnblogs.com/clrs97/p/5271148.html
Copyright © 2011-2022 走看看