测试地址:品酒大会
做法:本题需要用到后缀数组+并查集。
不难想到,对题目所给的字符串构造后缀数组,那么后缀数组上两个后缀之间最小的heightheightheight就是这两杯酒满足的最大相似度。我们要求的,实际上是对于每个相似值kkk,对于后缀数组上height" role="presentation" style="position: relative;">heightheightheight大于等于kkk的边连接成的每个连续区间求出方案数和最大乘积,然后对方案数累加,对最大乘积取最大值。不难看出若区间中包含i" role="presentation" style="position: relative;">iii个后缀,那么方案数有i(i−1)/2i(i−1)/2i(i-1)/2个,而最大乘积则有可能是区间中最大和次大值的乘积或最小和次小值的乘积(因为可能有负数,负负得正)。我们可以按照heightheightheight从大到小的顺序连边,然后合并区间的信息,很明显可以用并查集处理这一过程,然后这一题就做完了。
以下是本人代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll inf=1000000000;
int n,SA[300010],c[300010],x[600010]={0},s[300010],height[300010],Rank[300010];
int st[300010],top,fa[300010],order[300010];
char S[300010]={0};
ll a[300010],siz[300010]={0},cnt=0,ans=-inf*inf;
ll mx[300010],smx[300010],mn[300010],smn[300010],Cnt[300010],Ans[300010];void calc_SA()
{int p=1,tot=26;while (p<n){memset(c,0,sizeof(c));for(int i=1;i<=n;i++) c[x[i+p]]++;for(int i=1;i<=tot;i++) c[i]+=c[i-1];for(int i=tot;i>=1;i--) c[i]=c[i-1];c[0]=0;for(int i=1;i<=n;i++) s[++c[x[i+p]]]=i;memset(c,0,sizeof(c));for(int i=1;i<=n;i++) c[x[s[i]]]++;for(int i=1;i<=tot;i++) c[i]+=c[i-1];for(int i=tot;i>=1;i--) c[i]=c[i-1];c[0]=0;for(int i=1;i<=n;i++) SA[++c[x[s[i]]]]=s[i];tot=0;for(int i=1;i<=n;i++) {if (i==1||x[SA[i]]!=x[SA[i-1]]||x[SA[i]+p]!=x[SA[i-1]+p]) tot++;s[SA[i]]=tot;}for(int i=1;i<=n;i++) x[i]=s[i];if (tot==n) break;p<<=1;}for(int i=1;i<=n;i++)Rank[SA[i]]=i;
}void calc_height()
{for(int i=1,j=0;i<=n;i++,j=max(0,j-1)){if (Rank[i]==n) {height[Rank[i]]=j=0;continue;}while (S[i+j]==S[SA[Rank[i]+1]+j]) j++;height[Rank[i]]=j;}
}void init(int x)
{fa[x]=x;siz[x]=1;mx[x]=-inf*inf;smx[x]=-inf*inf;mn[x]=inf*inf;smn[x]=inf*inf;
}void insert(int x,ll y)
{if (y>=mx[x]) smx[x]=mx[x],mx[x]=y;else if (y>=smx[x]) smx[x]=y;if (y<=mn[x]) smn[x]=mn[x],mn[x]=y;else if (y<=smn[x]) smn[x]=y;
}int find(int x)
{int r=x,i=x,j;while (r!=fa[r]) r=fa[r];while (i!=r) {j=fa[i],fa[i]=r,i=j;}return r;
}void merge(int x,int y)
{int fx=find(x),fy=find(y);ll X=siz[fx],Y=siz[fy],Z=siz[fx]+siz[fy];fa[fy]=fx;siz[fx]+=siz[fy];insert(fx,mx[fy]);if (siz[fy]>1) insert(fx,smx[fy]);if (siz[fy]>2) insert(fx,mn[fy]);if (siz[fy]>3) insert(fx,smn[fy]);cnt=cnt-X*(X-1)/2-Y*(Y-1)/2+Z*(Z-1)/2;ans=max(ans,max(mx[fx]*smx[fx],mn[fx]*smn[fx]));
}void solve()
{memset(c,0,sizeof(c));for(int i=1;i<n;i++) c[height[i]]++;for(int i=1;i<n;i++) c[i]+=c[i-1];for(int i=n;i>=1;i--) c[i]=c[i-1];c[0]=0;for(int i=1;i<n;i++)order[++c[height[i]]]=i;for(int i=1;i<=n;i++){init(i);insert(i,a[SA[i]]);}int j=n-1;for(int i=n-1;i>=1;i--){while (height[order[i]]<j){Cnt[j]=cnt;Ans[j]=cnt?ans:0;j--;}merge(order[i],order[i]+1);}while (j>=0){Cnt[j]=cnt;Ans[j]=cnt?ans:0;j--;}
}int main()
{scanf("%d",&n);scanf("%s",S+1);for(int i=1;i<=n;i++)x[i]=S[i]-'a'+1;for(int i=1;i<=n;i++)scanf("%lld",&a[i]);calc_SA();calc_height();solve();for(int i=0;i<n;i++)printf("%lld %lld\n",Cnt[i],Ans[i]);return 0;
}

【BZOJ4199】品酒大会(NOI2015)-后缀数组+并查集相关推荐

  1. 【BZOJ4199】品酒大会,后缀数组+并查集维护

    Time:2016.05.23 Author:xiaoyimi 转载注明出处谢谢 传送门 题面及样例 思路: 求lcp相关问题上有类似于差异的地方,但不完全是,"差异"所求的是lc ...

  2. 【NOI2015】品酒大会【后缀数组】【并查集】

    传送门 传送门 题意:给一个长度为NNN的字符串和一个长度为NNN的序列AAA,对于所有的k∈[0,N−1]k \in [0,N-1]k∈[0,N−1],求选出两个数i,ji,ji,j满足lcp(su ...

  3. 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈

    P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...

  4. [BZOJ]4199: [Noi2015]品酒大会(后缀数组+笛卡尔树)

    Time Limit: 10 Sec  Memory Limit: 512 MB Description Input Output Sample Input 10 ponoiiipoi 2 1 4 7 ...

  5. P2178 后缀数组 + 并查集

    题目传送门 题意: 调酒师  调制了  杯鸡尾酒.这  杯鸡尾酒排成一行,其中第  杯酒被贴上了一个标签  ,每杯酒有一个美味值,每个标签都是  个小写英文字母之一,把这些酒想象为一个字符串  .两个 ...

  6. BZOJ 4199 [Noi2015]品酒大会(后缀自动机 + parent树上统计)

    4199: [Noi2015]品酒大会 Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 1598  Solved: 905 [Submit][Stat ...

  7. 花神游历各国 题解(小清新线段树/树状数组+并查集)

    题面 众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于 ...

  8. hdu 6200 mustedge mustedge mustedge(dfs序+树状数组+并查集)

    题目链接:hdu 6200 mustedge mustedge mustedge 题意: 一开始给你一个有n个节点m条无向边的图,现在定义mustedge为u->v的路径上必须经过的边. 现在有 ...

  9. sa后缀数组使用合集,包括height数组求LPC和LCS,ST表,单调队列优化。

    P5546 [POI2000]公共串 所有串合在一起,每两个串放不同的字符,求一遍后缀数组,然后利用height数组求LCS即可. #include<iostream> #include& ...

  10. POJ-2985(树状数组 + 并查集 + 二分)

    题目:http://poj.org/problem?id=2985 这题考察了两个点呢,组合并用到了并查集,求第K大的数用到了树状数组,刚开始WA了几次,发现是在组合并之后仅仅update(*, -1 ...

最新文章

  1. mysql 写锁需要等待读锁释放吗_Mysql实战45讲笔记:5、全局锁和表锁
  2. 开展企业网站建设如何做到保质保量?
  3. C言语for轮回语句
  4. C#学习路线:C#入门经典 -> CLR VIA C# -> WINDOWS核心编程
  5. 零起点学算法82——数组中查找数
  6. 在嵌入式Neo4j中使用Neo4j浏览器
  7. 037-PHP如何返回闭包函数实例
  8. idea怎么设置代码提示不区分大小写_IntelliJ IDEA 这样设置动图,棒极了!
  9. GDAL库调试(包括跨语言调试)
  10. 如何设置iPhone的手机铃声?【来自星星的你】
  11. MySQL开启命令自动补全功能(auto-rehash)
  12. 计算机专业大学排名_2020全国计算机专业大学排名
  13. 《论文写作》——课程总结
  14. shecodject生成免杀木马,一步过360、火绒
  15. 天津大学仁爱学院c语言期末考试题,天津大学仁爱学院2014-2015学年第1学期期末C语言复习.doc...
  16. 《从0到1上线微信小游戏》第九节 个人申请国家软件著作证书详细流程
  17. 五种典型开发周期模型(瀑布、V、原型化、螺旋、迭代)
  18. 【Python从0到1】第三篇:基础语法(三)
  19. 时序预测之三_傅立叶和小波变换
  20. 深度学习英文缩写_机器学习、深度学习……人工智能那些名词你知道几个?

热门文章

  1. 4D领导力打造卓越团队
  2. 地籍测量类毕业论文文献有哪些?
  3. linux怎么运行cu,Linux cu 命令
  4. PM_24 项目管理成熟度模型(了解)、26 知识产权与标准规范、收尾管理
  5. java 渲染_Java字体渲染
  6. 艺龙的执着与固执:等待微信
  7. 【目标检测数据集】一、PASCAL VOC数据集简介
  8. 吉比特2018校招 走格子游戏
  9. G-sensor 介绍
  10. Got permission denied while trying to connect to the Docker daemon socket