传送门->

又称普及大会。

这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对……

这题的输出和某两点相同后缀的长度有关,那么把串反过来就和相同前缀的长度有关。建出后缀自动机后,发现点u代表了right[u]个dis[fa[u]+1]~dis[u]相似的子串。此时如何统计答案就很显然了。

想着很简单,写着嘛…其实并不长?

  1. #include<algorithm>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<iomanip>
  7. #include<iostream>
  8. #include<map>
  9. #include<queue>
  10. #include<stack>
  11. #include<vector>
  12. #define rep(i,x,y) for(register LL i=(x);i<=(y);i++)
  13. #define dwn(i,x,y) for(register LL i=(x);i>=(y);i--)
  14. #define re register
  15. #define maxn 600010
  16. #define di ord[i]
  17. #define LL long long
  18. using namespace std;
  19. inline LL read()
  20. {
  21. LL x=0,f=1;
  22. char ch=getchar();
  23. while(isdigit(ch)==0 && ch!='-')ch=getchar();
  24. if(ch=='-')f=-1,ch=getchar();
  25. while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
  26. return x*f;
  27. }
  28. inline void write_(LL x)
  29. {
  30. LL f=0;char ch[20];
  31. if(!x){putchar('0'),putchar(' ');return;}
  32. if(x<0){putchar('-');x=-x;}
  33. while(x)ch[++f]=x%10+'0',x/=10;
  34. while(f)putchar(ch[f--]);
  35. putchar(' ');
  36. }
  37. inline void writen(LL x)
  38. {
  39. LL f=0;char ch[20];
  40. if(!x){puts("0");return;}
  41. if(x<0){putchar('-');x=-x;}
  42. while(x)ch[++f]=x%10+'0',x/=10;
  43. while(f)putchar(ch[f--]);
  44. putchar('\n');
  45. }
  46. LL ch[maxn][30],fa[maxn],r[maxn],dis[maxn],mn[maxn],mns[maxn],mx[maxn],mxs[maxn],lst,cnt;
  47. LL cc[maxn],ord[maxn],rt,n,a[maxn],ans[maxn],num[maxn],inf[4];
  48. char s[maxn];
  49. LL gx(char c){return c-'a';}
  50. void extend(char c)
  51. {
  52. LL np=++cnt,p=lst;dis[np]=dis[lst]+1,lst=np;
  53. for(;p&&!ch[p][gx(c)];p=fa[p])ch[p][gx(c)]=np;
  54. if(p==0)fa[np]=rt;
  55. else
  56. {
  57. LL q=ch[p][gx(c)];
  58. if(dis[q]==dis[p]+1)fa[np]=q;
  59. else
  60. {
  61. LL nq=++cnt;dis[nq]=dis[p]+1;
  62. fa[nq]=fa[q],fa[q]=fa[np]=nq;
  63. memcpy(ch[nq],ch[q],sizeof(ch[q]));
  64. for(;ch[p][gx(c)]==q;p=fa[p])ch[p][gx(c)]=nq;
  65. }
  66. }
  67. }
  68. void upd(LL x,LL y)
  69. {
  70. r[x]+=r[y];
  71. if(mn[x]<mn[y])mns[x]=min(mns[x],mn[y]);
  72. else mns[x]=min(mns[y],mn[x]),mn[x]=mn[y];
  73. if(mx[x]>mx[y])mxs[x]=max(mxs[x],mx[y]);
  74. else mxs[x]=max(mxs[y],mx[x]),mx[x]=mx[y];
  75. }
  76. LL mul(LL x)
  77. {
  78. LL tmx,tmn;
  79. if(mx[x]!=-inf[0]&&mxs[x]!=-inf[0])tmx=mx[x]*mxs[x];
  80. else tmx=-inf[0];
  81. if(mn[x]!=inf[0]&&mns[x]!=inf[0])tmn=mn[x]*mns[x];
  82. else tmn=-inf[0];
  83. return max(tmx,tmn);
  84. }
  85. void qsort()
  86. {
  87. memset(cc,0,sizeof(cc));
  88. rep(i,1,cnt)cc[dis[i]]++;
  89. rep(i,1,n)cc[i]+=cc[i-1];
  90. rep(i,1,cnt)ord[cc[dis[i]]--]=i;
  91. }
  92. int main()
  93. {
  94. n=read();
  95. lst=rt=++cnt;dis[0]=-1;
  96. scanf("%s",s+1);
  97. rep(i,1,n)a[i]=read();
  98. rep(i,1,(n>>1))swap(s[i],s[n-i+1]),swap(a[i],a[n-i+1]);
  99. rep(i,1,n)extend(s[i]);
  100. qsort();
  101. memset(inf,0x7f,sizeof(inf));
  102. rep(i,1,cnt)mx[i]=mxs[i]=ans[i]=-inf[0],mn[i]=mns[i]=inf[0];
  103. LL p=rt;
  104. rep(i,1,n)p=ch[p][gx(s[i])],mx[p]=mn[p]=a[i],r[p]=1;
  105. dwn(i,cnt,1)upd(fa[di],di);
  106. rep(i,1,cnt)
  107. ans[dis[i]]=max(mul(i),ans[dis[i]]),
  108. num[dis[fa[i]]+1]+=r[i]*(r[i]-1)/2,num[dis[i]+1]-=r[i]*(r[i]-1)/2;
  109. dwn(i,n,1)ans[i]=max(ans[i],ans[i+1]);
  110. rep(i,0,n-1)
  111. num[i]+=num[i-1],write_(num[i]),
  112. writen(num[i]==0?0:ans[i]);
  113. return 0;
  114. }
  115. /*
  116. 10
  117. ponoiiipoi
  118. 2 1 4 7 4 8 3 6 4 7
  119. */

  

据说用后缀数组也能做,不过思维难度略高。

要是觉得对后缀自动机还不够熟悉,可以试一下bzoj3238: [Ahoi2013],也是后缀自动机很好写(才怪)的题。

  1. #include<algorithm>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<iomanip>
  7. #include<iostream>
  8. #include<map>
  9. #include<queue>
  10. #include<stack>
  11. #include<vector>
  12. #define rep(i,x,y) for(register LL i=(x);i<=(y);++i)
  13. #define dwn(i,x,y) for(register LL i=(x);i>=(y);--i)
  14. #define re register
  15. #define maxn 1000010
  16. #define LL long long
  17. using namespace std;
  18. inline LL read()
  19. {
  20. LL x=0,f=1;
  21. char ch=getchar();
  22. while(isdigit(ch)==0 && ch!='-')ch=getchar();
  23. if(ch=='-')f=-1,ch=getchar();
  24. while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
  25. return x*f;
  26. }
  27. inline void write(LL x)
  28. {
  29. LL f=0;char ch[20];
  30. if(!x){puts("0");return;}
  31. if(x<0){putchar('-');x=-x;}
  32. while(x)ch[++f]=x%10+'0',x/=10;
  33. while(f)putchar(ch[f--]);
  34. putchar('\n');
  35. }
  36. LL ch[maxn][30],fa[maxn],dis[maxn],yes[maxn],lst,rt,cntnd;
  37. LL v[maxn],nxt[maxn],fir[maxn],siz[maxn],ans[maxn],cntrd,len;
  38. char s[maxn];
  39. void ade(LL u1,LL v1){v[++cntrd]=v1,nxt[cntrd]=fir[u1],fir[u1]=cntrd;}//u->v
  40. LL gx(char c){return c-'a';}
  41. void extend(char c)
  42. {
  43. LL np=++cntnd,p=lst;dis[np]=dis[p]+1,lst=np;
  44. for(;p&&ch[p][gx(c)]==0;p=fa[p])ch[p][gx(c)]=np;
  45. if(!p)fa[np]=rt;
  46. else
  47. {
  48. LL q=ch[p][gx(c)];
  49. if(dis[q]==dis[p]+1)fa[np]=q;
  50. else
  51. {
  52. LL nq=++cntnd;dis[nq]=dis[p]+1;
  53. fa[nq]=fa[q],fa[np]=fa[q]=nq;
  54. memcpy(ch[nq],ch[q],sizeof(ch[q]));
  55. for(;ch[p][gx(c)]==q;p=fa[p])ch[p][gx(c)]=nq;
  56. }
  57. }
  58. }
  59. void getans(LL u)
  60. {
  61. if(yes[u])siz[u]=1;
  62. LL tmp=0;
  63. for(LL k=fir[u];k!=-1;k=nxt[k])
  64. {
  65. getans(v[k]);
  66. siz[u]+=siz[v[k]];
  67. }
  68. for(LL k=fir[u];k!=-1;k=nxt[k])
  69. tmp+=siz[v[k]]*(siz[u]-siz[v[k]]);
  70. ans[u]=tmp*dis[u]+yes[u]*(siz[u]-1ll)*dis[u];
  71. }
  72. int main()
  73. {
  74. memset(fir,-1,sizeof(fir));
  75. memset(ans,0,sizeof(ans));
  76. lst=rt=++cntnd;dis[0]=-1;
  77. scanf("%s",s+1);
  78. len=strlen(s+1);
  79. rep(i,1,len)swap(s[i],s[len-i+1]);
  80. rep(i,1,len)extend(s[i]);
  81. LL p=rt;
  82. rep(i,1,cntnd)ade(fa[i],i);
  83. rep(i,1,len)p=ch[p][gx(s[i])],yes[p]=1;
  84. getans(rt);
  85. LL ansans=0;
  86. rep(i,1,cntnd)ansans+=ans[i];
  87. write((len+1ll)*len*(len-1ll)/2ll-ansans);
  88. return 0;
  89. }
  90. /*
  91. cacao
  92. */

 最后祝您身体健康,再见。

并不对劲的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. 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 ...

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

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

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

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

随机推荐

  1. 【数据传输 1】服务器—>客户端之间的数据类型转换

    导读:在做项目的时候,在controller中,将List数据类型转换为了JSON字符串,那么,为什么要将其数据转换为JOSN呢?这样的转换是否是必须的,在这个转换过程中,又经过了那些步骤?注:本篇博 ...

  2. C# 中的新增功能

    百度搜索:C# 中的新增功能 微软有站点专门介绍:C# 中的新增功能. 地址:https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/inde ...

  3. HDU-1210Eddy's 洗牌问题

    Eddy's 洗牌问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Prob ...

  4. hdu 3732

    #include<stdio.h> #include<string.h> int n,m,dp[10001]; int max(int a,int b) {  return a ...

  5. jmesa应用

    一直以来,都没发现什么好的分页组件,最初时用过displaytag,仔细研究了一下,发现它并没有别人说的那么强大,至少离自己的期望还很远,因此尝试寻找其它新的分页组件,但很久以来都没发现自己满意的.无 ...

  6. POJ 1502 水 dij

    题意:给N,表示N个节点. 给半个邻接矩阵,本身到本身的距离是0,边是双向的.当两个节点之间没有直接的边连接的时候,用x表示. 问从第一个节点到其他所有节点至少花费的时间. 这题唯一的处理是处理邻接矩 ...

  7. zookeeper原理浅析(一)

    参考:https://www.cnblogs.com/leocook/p/zk_0.html 代码:https://github.com/littlecarzz/zookeeper 1. 什么是Zoo ...

  8. easyshell 安装

    EasyShell是一个可以直接在Eclipse IDE中打开shell窗口的工具,在shell中运行选中的文件,打资源管理. 百度经验:jingyan.baidu.com 工具/原料 Easy_Sh ...

  9. Java生成验证码并进行验证(转)

    本文转自http://blog.csdn.net/worm0527/article/details/51030864 一.实现思路 使用BufferedImage用于在内存中存储生成的验证码图片 使用 ...

  10. (转)Delphi2009初体验 - 语言篇 - 智能指针(Smart Pointer)的实现

     转载:http://www.cnblogs.com/felixYeou/archive/2008/08/27/1277250.html 快速导航 一. 回顾历史二. 智能指针简介三. Delphi中 ...