• 【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]='
        ';
        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大佬的实现
      •  1 #include<bits/stdc++.h>
         2 #define inf 0x3f3f3f3f
         3 #define ll long long
         4 #define il inline 
         5 using namespace std;
         6 const int N=600010;
         7 int n,lst,w[N],len[N],sz,pa[N],mx0[N],mx1[N],mn0[N],mn1[N],ch[N][26],c[N],id[N],cnt[N];
         8 char s[N];
         9 ll ans1[N],ans2[N];
        10 il bool upd1(int x,int y){
        11     if(y==inf)return false;
        12     if(mx0[x]==inf||y>mx0[x]){mx1[x]=mx0[x];mx0[x]=y;return true;}
        13     if(mx1[x]==inf||y>mx1[x]){mx1[x]=y;return false;}
        14     return false;
        15 }
        16 il bool upd2(int x,int y){
        17     if(y==inf)return false;
        18     if(mn0[x]==inf||y<mn0[x]){mn1[x]=mn0[x];mn0[x]=y;return true;}
        19     if(mn1[x]==inf||y<mn1[x]){mn1[x]=y;return false;}
        20     return false;
        21 } 
        22 il void ins(int now,int x){
        23     int p=lst; int np=lst=++sz;
        24     cnt[np]=1;
        25     mx0[np]=mn0[np]=w[now];
        26     mx1[np]=mn1[np]=inf;
        27     len[np]=len[p]+1;
        28     while(p&&!ch[p][x])ch[p][x]=np,p=pa[p];
        29     if(!p){pa[np]=1;return;}
        30     int q=ch[p][x];
        31     if(len[q]==len[p]+1){pa[np]=q;}
        32     else {
        33         int nq=++sz; len[nq]=len[p]+1;
        34         memcpy(ch[nq],ch[q],sizeof(ch[q])); 
        35         pa[nq]=pa[q]; pa[q]=pa[np]=nq;
        36         while(p&&ch[p][x]==q)ch[p][x]=nq,p=pa[p]; 
        37     }
        38 }
        39 inline ll max(ll x,ll y){return x>y?x:y;}
        40 int main(){
        41     freopen("bzoj4199.in","r",stdin);
        42     freopen("bzoj4199.out","w",stdout);
        43     lst=sz=1; 
        44     memset(mx0,0x3f,sizeof(mx0));
        45     memset(mx1,0x3f,sizeof(mx1));
        46     memset(mn0,0x3f,sizeof(mn0));
        47     memset(mn1,0x3f,sizeof(mn1));
        48     scanf("%d%s",&n,s+1);
        49     for(int i=1;i<=n>>1;i++)swap(s[i],s[n-i+1]);
        50     for(int i=1;i<=n;i++)scanf("%d",&w[n-i+1]);
        51     for(int i=1;i<=n;i++)ins(i,s[i]-'a');
        52     for(int i=1;i<=sz;i++)c[len[i]]++;
        53     for(int i=1;i<=n;i++)c[i]+=c[i-1]; 
        54     for(int i=sz;i;i--)id[c[len[i]]--]=i,ans2[i]=-1e18;
        55     len[0]=-1;
        56     for(int i=sz;i;i--){
        57         int u=id[i];
        58         ll t1=(ll)cnt[u]*(cnt[u]-1)/2;
        59         ll t2=max((ll)mx0[u]*mx1[u], (ll)mn0[u]*mn1[u]); 
        60         ans1[len[u]]+=t1; 
        61         if(t1)ans2[len[u]]=max(ans2[len[u]],t2);
        62         ans1[len[pa[u]]]-=t1;
        63         cnt[pa[u]]+=cnt[u];
        64         if(upd1(pa[u],mx0[u]))upd1(pa[u],mx1[u]);
        65         if(upd2(pa[u],mn0[u]))upd2(pa[u],mn1[u]);
        66     }
        67     for(int i=n-1;~i;i--){
        68         ans1[i]+=ans1[i+1];
        69         ans2[i]=max(ans2[i],ans2[i+1]);
        70     }
        71     for(int i=0;i<n;i++){
        72         if(ans1[i])printf("%lld %lld
        ",ans1[i],ans2[i]);
        73         else puts("0 0");
        74     }
        75     return 0;
        76 }
        bzoj4199
  • 相关阅读:
    树莓派3下开启SSH服务
    没有显示器连接树莓派
    没有屏幕和键盘如何玩转树莓派
    无显示器通过网线连接笔记本电脑玩转树莓派
    解决某些软件无法在虚拟机中运行的方法
    sql注入-基于布尔型的盲注入门
    前台数据传到后台,日期类型序列化后与前台传过来的数据不一致
    layui修改表格行高
    jQuery动态回到顶部
    禁止选中页面内容
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10230485.html
Copyright © 2020-2023  润新知