题目描述

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

在大会的晚餐上,调酒师 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]品酒大会的更多相关文章

  1. 洛谷 P2178 [NOI2015]品酒大会 解题报告

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

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

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

  3. 洛谷P2178 [NOI2015]品酒大会(后缀自动机 线段树)

    题意 题目链接 Sol 说一个后缀自动机+线段树的无脑做法 首先建出SAM,然后对parent树进行dp,维护最大次大值,最小次小值 显然一个串能更新答案的区间是\([len_{fa_{x}} + 1 ...

  4. P2178 [NOI2015]品酒大会

    思路 在后缀树上进行一些操作就好了 后缀树上LCA的maxlen就是两个后缀的LCP的长度了 然后统计每个点作为LCA的次数和最大值.次大值.最小值.次小值 然后就做完了 代码 #include &l ...

  5. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

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

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

  7. 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集

    [BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...

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

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

  9. BZOJ_4199_[Noi2015]品酒大会_后缀自动机

    BZOJ_4199_[Noi2015]品酒大会_后缀自动机 Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席 ...

随机推荐

  1. 安装Ubuntu16.04卡在logo界面

    问题背景 笔者在使用U盘UEFI模式安装Ubuntu16.04时,遇到一个问题,即在BIOS里的boot设置U盘为第一启动项之后,启动,并没有顺利进入系统,而是卡在了logo界面.(PS:其实我等了它 ...

  2. fastjson中List和JSONArray的相互转换

    https://blog.csdn.net/xiaofei__/article/details/89571320 (1)List转换为JSONArray List<T> list = ne ...

  3. java多线程编程建议

    多线程编程建议 1,将应用设计成支持多线程并发,可提高性能 2,编写多线程程序,首先保证它是正确的,其次再考虑性能 3,同步处理的开销大于非同步处理,如果可能,尽量使用非同步处理 4,避免多个共享变量 ...

  4. 手机端META详细解释

    一.天猫 <title>天猫触屏版</title> <meta content="text/html; charset=utf-8" http-equ ...

  5. 第一次个人项目【词频统计】——PSP表格

    PSP2.1 任务内容 计划完成需要的时间(min) 实际完成需要的时间(min) Planning 计划 45 40 Estimate 估计这个任务需要多少时间,并规划大致工作步骤 30 20 De ...

  6. 移动端video视频播放问题

    1.视频播放后自动全屏 video添加playsinline  webkit-playsinline属性 2.安卓暂停或播放完毕不能滑动 通过js判断机型,安卓去掉controls属性,ios保留co ...

  7. C++与Matlab混合编程之:矩阵数据结构

    项目需要将matlab代码写成C++,准备用opencv.opencv中矩阵的存储与matlab有所不同,应注意以下问题: 1.matlab中矩阵是按照列优先存储的.对于n0*n1*...*nn维的矩 ...

  8. Web API 接口说明文档

    1.采用 Web API Help Page 显示效果 2.swaggerui 创建文档接口 效果图 3.swagger ui 安装配置 nuget 安装 2.设置xml文件 3.配置根路径 预览sw ...

  9. php filemtime filectime fileatime的区别

    1.fileatime()int fileatime(string filename):fileatime()函数返回filename最后访问的时间,这里的最后访问是指每当一个文件的数据块被读取,采用 ...

  10. HDU 6003 Problem Buyer

    贪心题(好久不做了) 题解 考虑最一般的,判断合法性? 经典贪心问题:左端点升序,左端点相同,右端点降序,c[i]升序 优先队列,每次选择覆盖x的右端点最小的区间. 称此方法为“区间匹配贪心” 最小的 ...