洛谷P2178 [NOI2015]品酒大会
题目描述
一年一度的“幻影阁夏日品酒大会”隆重开幕了。大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加。
在大会的晚餐上,调酒师 Rainbow 调制了 n 杯鸡尾酒。这 n 杯鸡尾酒排成一行,其中第 n 杯酒 (1 ≤ i ≤ n) 被贴上了一个标签 si ,每个标签都是26 个小写 英文字母之一。设 str(l,r) 表示第 l 杯酒到第 r 杯酒的 r - l + 1个标签顺次连接构成的字符串。若 str(p,p0)=str(q,q0),其中 1≤p≤p0≤n, 1≤q≤q0≤n, p≠q,p0−p+1=q0−q+1=r ,则称第 p 杯酒与第 q 杯酒是“ r 相似” 的。当然两杯“ r 相似”(r>1)的酒同时也是“ 1 相似”、“ 2 相似”、……、“ (r−1) 相似”的。特别地,对于任意的 1≤p,q≤n,p≠q,第 p 杯酒和第 q 杯酒都 是“ 0 相似”的。
在品尝环节上,品酒师 Freda 轻松地评定了每一杯酒的美味度,凭借其专业的水准和经验成功夺取了“首席品酒家”的称号,其中第 i 杯酒 (1≤i≤n) 的 美味度为ai 。现在 Rainbow 公布了挑战环节的问题:本次大会调制的鸡尾酒有一个特点,如果把第 p 杯酒与第 q 杯酒调兑在一起,将得到一杯美味度为 ap×aq 的 酒。现在请各位品酒师分别对于r=0,1,2,⋯,n−1 ,统计出有多少种方法可以 选出 2杯“ r 相似”的酒,并回答选择2 杯“r 相似”的酒调兑可以得到的美味度的最大值。
输入格式
第 1 行包含 1 个正整数 n ,表示鸡尾酒的杯数。
第 2 行包含一个长度为 n 的字符串 S,其中第 i 个字符表示第 i 杯酒的标签。
第 3 行包含 n 个整数,相邻整数之间用单个空格隔开,其中第i个整数表示第 i 杯酒的美味度ai 。
输出格式
包括 n 行。
第 i 行输出 2 个整数,中间用单个空格隔开。第 1 个整 数表示选出两杯“ (i−1) 相似”的酒的方案数,第 2 个整数表示选出两杯 “ (i−1) 相似”的酒调兑可以得到的最大美味度。若不存在两杯“(i−1) 相似” 的酒,这两个数均为 0 。
说明/提示
【样例说明 1】
用二元组 (p,q) 表示第 p 杯酒与第 q 杯酒。
0 相似:所有 45 对二元组都是 0 相似的,美味度最大的是 8×7=56。
1 相似:(1,8)(2,4)(2,9)(4,9)(5,6)(5,7)(5,10)(6,7)(6,10)(7,10),最大的 8×7=56 。
2 相似:(1,8)(4,9)(5,6) ,最大的4×8=32。
没有 3,4,5,⋯,9 相似的两杯酒,故均输出0 。
【时限1s,内存512M】
跳过其他同专题练习题的原因是,在写完P4248差异以后翻题解区看后缀树的做法,偶然看到有这么一句“品酒大会也可以用这个方法【单调栈】做”
于是我直奔品酒大会,读题五分钟…
恕鄙人才疏学浅,不懂单调栈单调队列,竟然愣是没看出来【事后发现好像真的有这种写法】
手推了一遍样例,感觉就是对于height数组的数值分组进行一堆统计,大数值可以为小数值的分组产生贡献。于是在草稿纸上按着height数组从大到小过了一遍,发现就是这样。但是同数值之间可以产生更复杂的联系,不一定在height定义的排名i和i-1这种范围内。只要前缀相同,排名为i的数组和i-2的数组可能也会产生贡献。
同时height为2的后缀也可能和height为1的后缀对1相似的答案产生贡献…这样又要考虑分组之间的关联。很容易想到倒着先处理height更大的后缀。
但是对于具体怎么处理还是有点头大。看了看刚刚按排名列出来的数组,花了一下产生贡献的分组,发现很显然能产生贡献的一大堆后缀都有相同的起始字母。从这里开始想到倒着处理所有操作,用并查集来维护同一个大组的信息。对于产生贡献的方案数,可以记录一个size数组,按秩合并。而对于最大值贡献,可以记录一下当前集合的最大a值即最大元素,以及当前集合内部元素已经产生的最大贡献。因为先处理的“x相似”的答案对更小的“y相似”的答案都可以产生贡献,所以在合并的时候直接全局变量维护方案数和最大值。
然后死在第二个样例。
仔细一看样例发现只记录集合最大元素显然会死,因为还有负数存在…负负得正,那就再记录一个最小值,一起维护。
然后疯狂通不过样例2,仔细一查居然打错了SA板子…把y[sa[i]]==y[sa[i-1]]写成了y[sa[i]]==y[sa[i]-1]【居然还能过样例1!!】过了样例满心欢喜地提交,被70分砸一脸。然后发现,初始化最小值要到long long的边界…这题数据大到吓死人。
inf设置成1e18,折腾一晚上终于AC。从开始想题到最后写完中间大概经历了三四个小时…期间还因为写炸并查集偷窥题解。怎么说呢,NOI的题果然不好做_(:з」∠)_
偷偷感谢题解区大佬。
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const long long maxn=;
const long long inf=1e18;
long long n,m,a[maxn];
long long ans[maxn],max1[maxn],ans1,ans2=-inf,number[maxn];
char s[maxn];
long long c[maxn],x[maxn],y[maxn],sa[maxn],fa[maxn],height[maxn],siz[maxn],maxx[maxn],minn[maxn];
vector<long long>h[maxn];
long long get(long long x){
if(fa[x]==x)return x;
else return fa[x]=get(fa[x]);
}
void getHEIGHT(){
long long k=;
for(long long i=;i<=n;i++){
if(x[i]==){
k=;
height[]=;
continue;
}
if(k)k--;
long long j=sa[x[i]-];
while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k])k++;
height[x[i]]=k;
}
}
void getSA(){
for(long long i=;i<=n;i++)c[s[i]]++,x[i]=s[i];
for(long long i=;i<=m;i++)c[i]+=c[i-];
for(long long i=n;i>=;i--)sa[c[x[i]]--]=i;
for(long long k=;k<=n;k<<=){
long long num=;
for(long long i=n-k+;i<=n;i++)y[++num]=i;
for(long long i=;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
for(long long i=;i<=m;i++)c[i]=;
for(long long i=;i<=n;i++)c[x[i]]++;
for(long long i=;i<=m;i++)c[i]+=c[i-];
for(long long i=n;i>=;i--)sa[c[x[y[i]]]--]=y[i],y[i]=;
swap(x,y);
x[sa[]]=;
num=;
for(long long i=;i<=n;i++){
x[sa[i]]=(y[sa[i]]==y[sa[i-]]&&y[sa[i]+k]==y[sa[i-]+k])?num:++num;
}
if(num==n)break;
m=num;
}
getHEIGHT();
}
void work(long long x,long long y){
if(siz[x]<siz[y])swap(x,y);
fa[y]=x;
ans1+=siz[x]*siz[y];
siz[x]+=siz[y];
number[x]=max(max(number[x],number[y]),max(maxx[x]*maxx[y],minn[x]*minn[y]));
maxx[x]=max(maxx[x],maxx[y]);
minn[x]=min(minn[x],minn[y]);
ans2=max(ans2,number[x]);
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
scanf("%lld",&n);
scanf("%s",s+);
for(int i=;i<=n;i++)scanf("%lld",&a[i]);
m=;
getSA();
for(int i=;i<=n;i++)h[height[i]].push_back(i);
for(long long i=;i<=n;i++){
fa[i]=i;
siz[i]=;
maxx[i]=minn[i]=a[sa[i]];
number[i]=-inf;
}
for(long long i=n-;i>=;i--){
for(long long j=;j<h[i].size();j++){
long long x=h[i][j];
work(get(x-),get(x));
}
if(ans1){
ans[i]=ans1;
max1[i]=ans2;
}
}
for(long long i=;i<n;i++){
printf("%lld %lld\n",ans[i],max1[i]);
}
return ;
}
洛谷P2178 [NOI2015]品酒大会的更多相关文章
- 洛谷 P2178 [NOI2015]品酒大会 解题报告
P2178 [NOI2015]品酒大会 题目描述 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发"首席品酒家"和 ...
- 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈
P2178 [NOI2015]品酒大会 题目链接 https://www.luogu.org/problemnew/show/P2178 题目描述 一年一度的"幻影阁夏日品酒大会" ...
- 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)
题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...
- P2178 [NOI2015]品酒大会
思路 在后缀树上进行一些操作就好了 后缀树上LCA的maxlen就是两个后缀的LCP的长度了 然后统计每个点作为LCA的次数和最大值.次大值.最小值.次小值 然后就做完了 代码 #include &l ...
- BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]
4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
[BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- BZOJ_4199_[Noi2015]品酒大会_后缀自动机
BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...
随机推荐
- 期望——邮票收集问题lightoj1342
邮票手机问题: 有n种类型的邮票,问将所有的类型的邮票全部收集起来所要的收集次数期望是多少. 设dp[i]为已经收集了i种类型的票,还要收集n-i种的次数的期望. dp[n]=0; 递推式: dp[i ...
- 安装zabbix需要php的两个模块php-bcmath和php-mbstring(转)
安装zabbix需要php的两个模块php-bcmath和php-mbstring 原创 Linux操作系统 作者:甲骨文技术支持 时间:2018-02-24 18:35:24 1472 0 1. ...
- Installer - win10安装及卸载SQL Server2008数据库
一.数据库安装环境 操作系统:win10 SQL server:SQL server 2008 R2 二.全新数据库安装 1.安装扩展文件 双击安装文件,弹出如下窗体: ...
- iOS开发使用UIScrollView随笔
1.scrollview滚动到固定偏移量contenOffset - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)anim ...
- 《DSP using MATLAB》Problem 8.11
代码: %% ------------------------------------------------------------------------ %% Output Info about ...
- Teigha克隆db的blockTableRecord里面的一个实体
std::vector<OdDbEntityPtr> entities; OdDbBlockTableRecordPtr blkTblRcd = blockId.openObject(); ...
- 初识splay
这东西都没什么板子着实让我很难受啊,只能到网上抄抄补补, 记下两个用到的博客 https://blog.csdn.net/clove_unique/article/details/50630280 h ...
- Android 开发 防止按键连续点击
前言 按键防止连续点击是任何一个项目都要考虑的功能.下面我们将介绍几种防止按键连续点击的方法 用工具类实现 /** *@content:按键延时工具类,用于防止按键连点 *@time:2019-5-1 ...
- 测试是否是移动端,是否是iphone,是否是安卓
function isMobile(){ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(na ...
- [编织消息框架][netty源码分析]11 ByteBuf 实现类UnpooledHeapByteBuf职责与实现
每种ByteBuf都有相应的分配器ByteBufAllocator,类似工厂模式.我们先学习UnpooledHeapByteBuf与其对应的分配器UnpooledByteBufAllocator 如何 ...