BZOJ4199:[NOI2015]品酒大会——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4199
https://www.luogu.org/problemnew/show/P2178#sub
一年一度的“幻影阁夏日品酒大会”隆重开幕了。大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加。
在大会的晚餐上,调酒师 Rainbow 调制了 n 杯鸡尾酒。这 n 杯鸡尾酒排成一行,其中第 n 杯酒 (1 ≤ i ≤ n) 被贴上了一个标签si,每个标签都是 26 个小写 英文字母之一。设 str(l, r)表示第 l 杯酒到第 r 杯酒的 r − l + 1 个标签顺次连接构成的字符串。若 str(p, po) = str(q, qo),其中 1 ≤ p ≤ po ≤ n, 1 ≤ q ≤ qo ≤ n, p ≠ q, po − p + 1 = qo − 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 相似”的酒调兑可以得到的美味度的最大值。
参考:https://blog.csdn.net/alxpcun/article/details/50482493
题意很绕,看了半个小时没看懂求助题解得到了一个言简意赅的题意:
后缀都有价值,找到两个后缀,他们的公共前缀长为r则称他们"r"相似,求对于所有r取值有多少个"r"相似以及两个后缀价值积最大。
暴力:枚举r,用height数组分块,对于大小为n的块显然是有n*(n-1)/2对合法解,同时维护块的最大次大值和最小次小值来更新答案即可。
(因为价值有负数,所以不仅要考虑最大值的乘积,还要考虑最小值的乘积。)
正解:我们知道height小值会影响height大值的影响,换言之大值不会影响小值。
所以我们对height数组排序,从后往前枚举r,每次继承前一个r的所有答案开始更新。
用并查集维护一下当前height的后缀之间的关系,这样在整个并查集里面都是两两为"r"相似的对。
- #include<cstdio>
- #include<cmath>
- #include<iostream>
- #include<vector>
- #include<cstring>
- #include<algorithm>
- #include<cctype>
- using namespace std;
- typedef long long ll;
- const int N=3e5+;
- const ll INF=1e18;
- char s[N];
- int n,m,rk[N],sa[N],w[N],fa[N],height[N];
- ll a[N],ans[N][],size[N],maxn[N],minn[N];
- struct node{
- int h,x,y;
- }g[N];
- inline bool cmp(node wa,node wb){
- return wa.h>wb.h;
- }
- inline bool pan(int *x,int i,int j,int k){
- int ti=i+k<n?x[i+k]:-;
- int tj=j+k<n?x[j+k]:-;
- return ti==tj&&x[i]==x[j];
- }
- void SA_init(){
- int *x=rk,*y=height,r=;
- for(int i=;i<r;i++)w[i]=;
- for(int i=;i<n;i++)w[s[i]]++;
- for(int i=;i<r;i++)w[i]+=w[i-];
- for(int i=n-;i>=;i--)sa[--w[s[i]]]=i;
- r=;x[sa[]]=;
- for(int i=;i<n;i++)
- x[sa[i]]=s[sa[i]]==s[sa[i-]]?r-:r++;
- for(int k=;r<n;k<<=){
- int yn=;
- for(int i=n-k;i<n;i++)y[yn++]=i;
- for(int i=;i<n;i++)
- if(sa[i]>=k)y[yn++]=sa[i]-k;
- for(int i=;i<r;i++)w[i]=;
- for(int i=;i<n;i++)w[x[y[i]]]++;
- for(int i=;i<r;i++)w[i]+=w[i-];
- for(int i=n-;i>=;i--)sa[--w[x[y[i]]]]=y[i];
- swap(x,y);r=;x[sa[]]=;
- for(int i=;i<n;i++)
- x[sa[i]]=pan(y,sa[i],sa[i-],k)?r-:r++;
- }
- }
- void height_init(){
- int i,j,k=;
- for(int i=;i<=n;i++)rk[sa[i]]=i;
- for(int i=;i<n;i++){
- if(k)k--;
- int j=sa[rk[i]-];
- while(s[i+k]==s[j+k])k++;
- height[rk[i]]=k;
- }
- }
- int find(int x){
- if(x==fa[x])return x;
- return fa[x]=find(fa[x]);
- }
- void unionn(int x,int y){
- if(size[x]>size[y])swap(x,y);
- fa[x]=y,size[y]+=size[x];
- maxn[y]=max(maxn[x],maxn[y]);
- minn[y]=min(minn[x],minn[y]);
- }
- void solve(){
- for(int i=;i<=n;i++)g[i-]=(node){height[i],i,i-};
- sort(g+,g+n,cmp);
- for(int i=g[].h,j=;i>=;i--){
- ans[i][]=ans[i+][];ans[i][]=ans[i+][];
- for(;j<n&&g[j].h==i;j++){
- int x=find(g[j].x),y=find(g[j].y);
- if(x==y)continue;
- ans[i][]=max(ans[i][],maxn[x]*maxn[y]);
- ans[i][]=max(ans[i][],minn[x]*minn[y]);
- ans[i][]+=size[x]*size[y];
- unionn(x,y);
- }
- }
- }
- int main(){
- scanf("%d%s",&n,s);
- for(int i=;i<=n;i++)ans[i][]=-INF;
- s[n++]=;
- SA_init();
- n--;
- height_init();
- for(int i=;i<=n;i++){
- scanf("%lld",&a[i]);
- maxn[rk[i-]]=a[i],minn[rk[i-]]=a[i];
- fa[i]=i;size[i]=;
- }
- solve();
- for(int i=;i<n;i++)
- printf("%lld %lld\n",ans[i][],ans[i][]?ans[i][]:);
- return ;
- }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4199:[NOI2015]品酒大会——题解的更多相关文章
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- [bzoj4199][Noi2015]品酒大会_后缀自动机_后缀树_树形dp
品酒大会 bzoj-4199 Noi-2015 题目大意:给定一个字符串,如果其两个子串的前$r$个字符相等,那么称这两个子串的开头两个位置$r$相似.如果两个位置勾兑在一起那么美味度为两个位置的乘积 ...
- [BZOJ4199][NOI2015]品酒大会
#131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...
- bzoj4199: [Noi2015]品酒大会(后缀数组)
题目描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainb ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- 并不对劲的bzoj4199: [Noi2015]品酒大会
传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...
- 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 ...
- bzoj千题计划257:bzoj4199: [Noi2015]品酒大会
http://www.lydsy.com/JudgeOnline/problem.php?id=4199 求出后缀数组的height 从大到小枚举,合并 维护组内 元素个数,最大.次大.最小.次小 # ...
随机推荐
- dota2交换物品
改成.bat 因为文件就可以 echo/>>c:/windows/system32/drivers/etc/hostsecho 111.230.82.224 steamcommunity. ...
- 修改Eclipse中项目在Apache Tomcat中的部署路径
在Eclipse中配项目已经部署到如下默认目录下:eclipse workspace/.metadata/.plugins/org.eclipse.core.resources/.projects. ...
- Use GitHub Desktop to get GitHub projects
Find the project's https git file in the home page of the project. e.g. https://github.com/PrismLibr ...
- 不老的神器--namp,awvs
要会使用的工具 NESSUS nmap awvs hydra burpsuit 工具的话,都有文档,应该多使用 -h 多看官方文档,就会用了. 1.namp基本用法 -iL <inputfile ...
- 怎样安装JMeter
JMeter有图形界面, 而且支持中文! JMeter官网地址: http://jmeter.apache.org/ 点击左上角的下载: 点击下面的.zip后缀的压缩包: 解压到本地: JMeter目 ...
- JavaWeb--------JSP语法基础学习(特别适合入门)
准备工作: 需要Tomcat8.0,MyEclipse,JDK JSP是一种运行在服务器端的脚本语言,JSP页面又是基于HTML网页的程序,它是Java Web 开发技术的基础. 基本内容: JSP页 ...
- Response对象及常用方法
void addCookie(Cookie cookie)给客户端添加一个Cookie对象,以保存客户端的信息 void addDateHeader(String name,long value) 添 ...
- 更新字典 (Updating a Dictionary,UVa12504)
题目描述: 解题思路: 1.根据:和,获得字符串 2.使用两个map进行比较: #include <iostream> #include <algorithm> #includ ...
- FPGA学习-PS2接口
选自http://m.elecfans.com/article/774143.html
- Machine Learning笔记整理 ------ (三)基本性能度量
1. 均方误差,错误率,精度 给定样例集 (Example set): D = {(x1, y1), (x2, y2), (x3, y3), ......, (xm, ym)} 其中xi是对应属性的值 ...