【bzoj4199】【Noi2015】品酒大会

【bzoj4199】【Noi2015】品酒大会

【bzoj4199】【Noi2015】品酒大会

    • SA+并查集
    •  把ht按大小倒序加入,并查集合并维护答案的变化;
    • SAM
    • 翻转串,求出SAM的parent树就是后缀树,两个串的最长公共后缀是他们lca的len值;
    • 考率一个节点x,那么它子树里的后缀点两两都是len[x]相似的,所以在prent树上做dp即可;
    • 第二问的统计比较麻烦,可以直接写一个后缀树的dfs来统计u的当前儿子和之前的儿子的答案,这样子不用维护次大值;
    • dp的具体方式见bzoj3238  
    •  1 #include<bits/stdc++.h>
       2 #define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
       3 #define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
       4 #define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
       5 #define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
       6 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
       7 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
       8 using namespace std;
       9 char ss[1<<17],*A=ss,*B=ss;
      10 inline char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<17,stdin),A==B)?-1:*A++;}
      11 template<class T>inline void sd(T&x){
      12     char c;T y=1;while(c=gc(),(c<48||57<c)&&c!=-1)if(c==45)y=-1;x=c-48;
      13     while(c=gc(),47<c&&c<58)x=x*10+c-48;x*=y;
      14 }
      15 inline void gs(char*s){char c;while(c=gc(),c<32);*s++=c;while(c=gc(),c>32)*s++=c;}
      16 char sr[1<<21],z[20];int C=-1,Z;
      17 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
      18 template<class T>inline void we(T x){
      19     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
      20     while(z[++Z]=x%10+48,x/=10);
      21     while(sr[++C]=z[Z],--Z);sr[++C]=' ';
      22 }
      23 const int N=3e5+5,M=2*N,inf=1e9+7;
      24 typedef long long ll;
      25 typedef int arr[M];
      26 int n,w[N];char s[N];
      27 struct SAM{
      28     int las,T,ch[M][26];arr fa,len,sz;
      29     SAM(){las=T=1;}
      30     inline void ins(int c,int w){
      31         int p=las,np;fa[np=las=++T]=1,len[np]=len[p]+1;
      32         for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
      33         mx[T]=mi[T]=w,mx2[T]=-inf,mi2[T]=inf,sz[T]=1;
      34         if(p){
      35             int q=ch[p][c],nq;
      36             if(len[p]+1==len[q])fa[np]=q;
      37             else{
      38                 nq=++T;mx[T]=mx2[T]=-inf,mi[T]=mi2[T]=inf;
      39                 fa[nq]=fa[q],len[nq]=len[p]+1,memcpy(ch[nq],ch[q],4*26);
      40                 for(fa[np]=fa[q]=nq;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
      41             }
      42         }
      43     }
      44     struct eg{int nx,to;}e[M];
      45     int ce;arr fi,mx,mx2,mi,mi2,sx;ll sum[M],ans[M];
      46     inline void add(int u,int v){e[++ce]=(eg){fi[u],v},fi[u]=ce;}
      47     inline void ck1(int u,int w){if(w>mx[u])mx2[u]=mx[u],mx[u]=w;else if(w>mx2[u])mx2[u]=w;}
      48     inline void ck2(int u,int w){if(w<mi[u])mi2[u]=mi[u],mi[u]=w;else if(w<mi2[u])mi2[u]=w;}
      49     void dfs(int u){
      50         int siz=0;
      51         go(u){
      52             dfs(v);siz+=sz[v];
      53             ck1(u,mx[v]),ck1(u,mx2[v]);
      54             ck2(u,mi[v]),ck2(u,mi2[v]);
      55 
      56         }if(siz+sz[u]<2)return;
      57         cmax(ans[len[u]],max((ll)mx[u]*mx2[u],(ll)mi[u]*mi2[u]));
      58         go(u)sum[len[u]]+=(ll)sz[u]*sz[v],sz[u]+=sz[v];
      59     }
      60     inline void sol(){
      61         mx[1]=mx2[1]=-inf,mi[1]=mi2[1]=inf;
      62         memset(ans,-63,sizeof ans);
      63         fp(i,2,T)add(fa[i],i);dfs(1);
      64         fd(i,n-1,0)sum[i]+=sum[i+1],cmax(ans[i],ans[i+1]);
      65         fp(i,0,n-1)we(sum[i]),we(!sum[i]?0:ans[i]),sr[++C]='\n';
      66     }
      67 }p;
      68 int main(){
      69     #ifndef ONLINE_JUDGE
      70         file("s");
      71     #endif
      72     sd(n),gs(s+1);fp(i,1,n)sd(w[i]);
      73     fd(i,n,1)p.ins(s[i]-'a',w[i]);p.sol();
      74 return Ot(),0;
      75 }
      76 //https://kelin.blog.luogu.org/solution-p2178
      推荐luogu大佬的实现

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-24
  • 2021-06-02
猜你喜欢
  • 2021-10-25
  • 2022-03-05
  • 2021-08-05
  • 2021-11-25
  • 2021-10-15
相关资源
相似解决方案