• 题解

    • SA+并查集
    • 把ht按大小倒序加入,并查集合并维护答案的变化;
    • SAM
    • 翻转串,求出SAM的parent树就是后缀树,两个串的最长公共后缀是他们lca的len值;
    • 考率一个节点x,那么它子树里的后缀点两两都是len[x]相似的,所以在prent树上做dp即可;
    • 第二问的统计比较麻烦,可以直接写一个后缀树的dfs来统计u的当前儿子和之前的儿子的答案,这样子不用维护次大值;
    • dp的具体方式见bzoj3238
    •  #include<bits/stdc++.h>
      #define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
      #define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
      #define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
      #define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
      template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
      template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,:;}
      using namespace std;
      char ss[<<],*A=ss,*B=ss;
      inline char gc(){return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?-:*A++;}
      template<class T>inline void sd(T&x){
      char c;T y=;while(c=gc(),(c<||<c)&&c!=-)if(c==)y=-;x=c-;
      while(c=gc(),<c&&c<)x=x*+c-;x*=y;
      }
      inline void gs(char*s){char c;while(c=gc(),c<);*s++=c;while(c=gc(),c>)*s++=c;}
      char sr[<<],z[];int C=-,Z;
      inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
      template<class T>inline void we(T x){
      if(C><<)Ot();if(x<)sr[++C]=,x=-x;
      while(z[++Z]=x%+,x/=);
      while(sr[++C]=z[Z],--Z);sr[++C]=' ';
      }
      const int N=3e5+,M=*N,inf=1e9+;
      typedef long long ll;
      typedef int arr[M];
      int n,w[N];char s[N];
      struct SAM{
      int las,T,ch[M][];arr fa,len,sz;
      SAM(){las=T=;}
      inline void ins(int c,int w){
      int p=las,np;fa[np=las=++T]=,len[np]=len[p]+;
      for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
      mx[T]=mi[T]=w,mx2[T]=-inf,mi2[T]=inf,sz[T]=;
      if(p){
      int q=ch[p][c],nq;
      if(len[p]+==len[q])fa[np]=q;
      else{
      nq=++T;mx[T]=mx2[T]=-inf,mi[T]=mi2[T]=inf;
      fa[nq]=fa[q],len[nq]=len[p]+,memcpy(ch[nq],ch[q],*);
      for(fa[np]=fa[q]=nq;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
      }
      }
      }
      struct eg{int nx,to;}e[M];
      int ce;arr fi,mx,mx2,mi,mi2,sx;ll sum[M],ans[M];
      inline void add(int u,int v){e[++ce]=(eg){fi[u],v},fi[u]=ce;}
      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;}
      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;}
      void dfs(int u){
      int siz=;
      go(u){
      dfs(v);siz+=sz[v];
      ck1(u,mx[v]),ck1(u,mx2[v]);
      ck2(u,mi[v]),ck2(u,mi2[v]); }if(siz+sz[u]<)return;
      cmax(ans[len[u]],max((ll)mx[u]*mx2[u],(ll)mi[u]*mi2[u]));
      go(u)sum[len[u]]+=(ll)sz[u]*sz[v],sz[u]+=sz[v];
      }
      inline void sol(){
      mx[]=mx2[]=-inf,mi[]=mi2[]=inf;
      memset(ans,-,sizeof ans);
      fp(i,,T)add(fa[i],i);dfs();
      fd(i,n-,)sum[i]+=sum[i+],cmax(ans[i],ans[i+]);
      fp(i,,n-)we(sum[i]),we(!sum[i]?:ans[i]),sr[++C]='\n';
      }
      }p;
      int main(){
      #ifndef ONLINE_JUDGE
      file("s");
      #endif
      sd(n),gs(s+);fp(i,,n)sd(w[i]);
      fd(i,n,)p.ins(s[i]-'a',w[i]);p.sol();
      return Ot(),;
      }
      //https://kelin.blog.luogu.org/solution-p2178

      推荐luogu大佬的实现

    •  #include<bits/stdc++.h>
      #define inf 0x3f3f3f3f
      #define ll long long
      #define il inline
      using namespace std;
      const int N=;
      int n,lst,w[N],len[N],sz,pa[N],mx0[N],mx1[N],mn0[N],mn1[N],ch[N][],c[N],id[N],cnt[N];
      char s[N];
      ll ans1[N],ans2[N];
      il bool upd1(int x,int y){
      if(y==inf)return false;
      if(mx0[x]==inf||y>mx0[x]){mx1[x]=mx0[x];mx0[x]=y;return true;}
      if(mx1[x]==inf||y>mx1[x]){mx1[x]=y;return false;}
      return false;
      }
      il bool upd2(int x,int y){
      if(y==inf)return false;
      if(mn0[x]==inf||y<mn0[x]){mn1[x]=mn0[x];mn0[x]=y;return true;}
      if(mn1[x]==inf||y<mn1[x]){mn1[x]=y;return false;}
      return false;
      }
      il void ins(int now,int x){
      int p=lst; int np=lst=++sz;
      cnt[np]=;
      mx0[np]=mn0[np]=w[now];
      mx1[np]=mn1[np]=inf;
      len[np]=len[p]+;
      while(p&&!ch[p][x])ch[p][x]=np,p=pa[p];
      if(!p){pa[np]=;return;}
      int q=ch[p][x];
      if(len[q]==len[p]+){pa[np]=q;}
      else {
      int nq=++sz; len[nq]=len[p]+;
      memcpy(ch[nq],ch[q],sizeof(ch[q]));
      pa[nq]=pa[q]; pa[q]=pa[np]=nq;
      while(p&&ch[p][x]==q)ch[p][x]=nq,p=pa[p];
      }
      }
      inline ll max(ll x,ll y){return x>y?x:y;}
      int main(){
      freopen("bzoj4199.in","r",stdin);
      freopen("bzoj4199.out","w",stdout);
      lst=sz=;
      memset(mx0,0x3f,sizeof(mx0));
      memset(mx1,0x3f,sizeof(mx1));
      memset(mn0,0x3f,sizeof(mn0));
      memset(mn1,0x3f,sizeof(mn1));
      scanf("%d%s",&n,s+);
      for(int i=;i<=n>>;i++)swap(s[i],s[n-i+]);
      for(int i=;i<=n;i++)scanf("%d",&w[n-i+]);
      for(int i=;i<=n;i++)ins(i,s[i]-'a');
      for(int i=;i<=sz;i++)c[len[i]]++;
      for(int i=;i<=n;i++)c[i]+=c[i-];
      for(int i=sz;i;i--)id[c[len[i]]--]=i,ans2[i]=-1e18;
      len[]=-;
      for(int i=sz;i;i--){
      int u=id[i];
      ll t1=(ll)cnt[u]*(cnt[u]-)/;
      ll t2=max((ll)mx0[u]*mx1[u], (ll)mn0[u]*mn1[u]);
      ans1[len[u]]+=t1;
      if(t1)ans2[len[u]]=max(ans2[len[u]],t2);
      ans1[len[pa[u]]]-=t1;
      cnt[pa[u]]+=cnt[u];
      if(upd1(pa[u],mx0[u]))upd1(pa[u],mx1[u]);
      if(upd2(pa[u],mn0[u]))upd2(pa[u],mn1[u]);
      }
      for(int i=n-;~i;i--){
      ans1[i]+=ans1[i+];
      ans2[i]=max(ans2[i],ans2[i+]);
      }
      for(int i=;i<n;i++){
      if(ans1[i])printf("%lld %lld\n",ans1[i],ans2[i]);
      else puts("0 0");
      }
      return ;
      }

      bzoj4199

【bzoj4199】【Noi2015】品酒大会的更多相关文章

  1. [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  2. [UOJ#131][BZOJ4199][NOI2015]品酒大会

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  3. [bzoj4199][Noi2015]品酒大会_后缀自动机_后缀树_树形dp

    品酒大会 bzoj-4199 Noi-2015 题目大意:给定一个字符串,如果其两个子串的前$r$个字符相等,那么称这两个子串的开头两个位置$r$相似.如果两个位置勾兑在一起那么美味度为两个位置的乘积 ...

  4. [BZOJ4199][NOI2015]品酒大会

    #131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...

  5. bzoj4199: [Noi2015]品酒大会(后缀数组)

    题目描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainb ...

  6. BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】

    题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...

  7. 并不对劲的bzoj4199: [Noi2015]品酒大会

    传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...

  8. 2019.02.28 bzoj4199: [Noi2015]品酒大会(sam+线段树)

    传送门 题意:给一个串,每个位置有一个权值,当S[s...s+len−1]=S[t...t+len−1]&&S[s...s+len]̸=S[t..t+len]S[s...s+len-1 ...

  9. bzoj千题计划257:bzoj4199: [Noi2015]品酒大会

    http://www.lydsy.com/JudgeOnline/problem.php?id=4199 求出后缀数组的height 从大到小枚举,合并 维护组内 元素个数,最大.次大.最小.次小 # ...

  10. [BZOJ4199][Noi2015]品酒大会 树形DP+后缀自动机

    由于要找后缀的前缀,所以先用反串建立SAM. link边组成了后缀树. 两个子串的最长公共前缀是LCA的step 树形dp即可. #include<iostream> #include&l ...

随机推荐

  1. 学习笔记 | Github

    Github教程 \(Github\)是个好东西QwQ 存代码不用U盘爸爸妈妈再也不用担心我的U盘弄丢没有备份啦! 创建github账号 创建仓库 输入命令 git clone https://git ...

  2. C++ 函数 引用

    一.引用的概念 引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样.引用的声明方法: 类型标识符 &引用名 = 目标变量名: 为一个变量起一个别名.假如有一个变量a,想给 ...

  3. 团队项目M1阶段个人反思

    郑培蕾: 作为项目的PM,我前期的工作还是有很大的缺陷的,因为没有在开发之前对项目进行一个合理的评估,所以后来分配任务的时候就很不科学, 而且任务分配的比较粗糙,没有细化到每个人每天应该做什么,这就导 ...

  4. “学霸系统”app——NABC

    “学霸系统”客户端项目是我们小组本次的课题. 一.需求(need) 对于这款软件,我们的目标是在手机端移植并实现网页端已有的用户管理.搜索.分类.上传下载.用户贡献与交互等功能,从而完成从PC到终端的 ...

  5. Fourteenth scrum meeting

    闫昊 今日完成:整理上一阶段代码,规划第二阶段实施过程 明日完成:学习讨论区开发 唐彬 今日完成:整理上一阶段代码,规划第二阶段实施过程 明日完成:学习学习进度部分开发 史烨轩 今日完成:整理上一阶段 ...

  6. Chapter 10 软件测试

    软件测试是软件质量保证的一项关键活动,验证与确认是贯穿软件生命周期的规范化评估方法.软件验证则试图证明在软件生存的各个阶段是否满足客户的需求,软件确认是一系列的活动和过程,两个活动相互独立但却相辅相成 ...

  7. 《UML大战需求分析》-读后感二

    活动图将流成分解为一个一个的活动,通过活动的先后顺序来展示流程,而状态机图是从某个事物的状态是如何转变的角度来展示流程,首先确定事物,然后找出状态,状态之间的箭头叫转换,箭头上的文字说明了是什么事情导 ...

  8. IT职业道路的苦与甜

    每当有人问起你学的是什么专业啊?学的怎么样啊?好不好学啊?等等一些类似的问题.我都会默默的说一句,会者不难,难者不会.当然现在的我还处于菜鸟级别,不过我相信在不久后的一天我一定会脱离菜鸟的行列,然后挺 ...

  9. 超实用 1 ArrayList 链表

    package ArrayList链表; import java.util.*; public class kk1 { /** * 作者:Mr.Fan * 功能:记住ArrayList链表 */ pu ...

  10. Internet 校验和的数学性质

    Internet 校验和(Checksum)仅计算头部的正确性,这一点很重要,这意味着 IP 协议不检查 IPv4 packet 有效载荷部分的数据正确性.为了保证有效载荷部分的正常传输,其他协议必须 ...