BZOJ4199/UOJ131 [Noi2015]品酒大会
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:UOJ131
正解:后缀数组
解题报告:
考虑两杯酒如果r相似,显然也会r-1相似、r-2相似…
那么我肯定是从大往小做,大的做完了的贡献可以直接合并进小的。
我们先构出后缀数组,得到height数组。
把height数组排个序,可以得到最大的height,那么超过这个最大的显然无解。
那么我每次把两个相邻的部分所在的集合合并,合并时计算一下对于当前集合的贡献,ans就是两个max或者min乘起来,cnt就是两个cnt相乘。
就做完了,板子题做起来还是挺simple的…
//It is made by ljh2000
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <ctime>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <string>
#include <complex>
using namespace std;
typedef long long LL;
const int MAXN = 300011;
const LL inf = (1LL<<62);
int n,rank[MAXN],sa[MAXN],wa[MAXN],wb[MAXN],c[MAXN],height[MAXN];
char ch[MAXN];
int father[MAXN],w[MAXN];
LL ans[MAXN],cnt[MAXN],size[MAXN],maxl[MAXN],minl[MAXN]; struct node{ int h,id; }a[MAXN];
inline bool cmp(node q,node qq){ return q.h>qq.h; }
inline int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; } inline int getint(){
int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
} inline void build(int m){
int *x=wa,*y=wb;
for(int i=1;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[x[i]=(ch[i]-'a'+1)]++;
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=1;i<=n;i++) sa[c[x[i]]--]=i;
for(int k=1,p;k<=n;k<<=1) {
p=0; for(int i=n-k+1;i<=n;i++) y[++p]=i;
for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
for(int i=1;i<=m;i++) c[i]=0;
for(int i=1;i<=n;i++) c[x[y[i]]]++;
for(int i=2;i<=m;i++) c[i]+=c[i-1];
for(int i=n;i>=1;i--)/*!!!*/ sa[c[x[y[i]]]--]=y[i];//!!!
swap(x,y); p=1; x[sa[1]]=1;
for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k])?p:++p;
m=p; if(p==n) break;
}
} inline void calc_height(){
int i=1,j,k=0; for(int i=1;i<=n;i++) rank[sa[i]]=i;
for(;i<=n;height[rank[i++]]=k/*!!!*/)
for(k?k--:0 ,j=sa[rank[i]-1];ch[i+k]==ch[j+k];k++) ;
} inline void work(){
n=getint(); scanf("%s",ch+1); for(int i=1;i<=n;i++) w[i]=getint();
build(256); calc_height(); for(int i=1;i<=n;i++) ans[i]=-inf;
for(int i=2;i<=n;i++) a[i-1].h=height[i],a[i-1].id=i/*!!!*/;
sort(a+1,a+n,cmp); int now=1,r1,r2,x,y;
for(int i=1;i<=n;i++) size[i]=1,father[i]=i,maxl[rank[i]]=minl[rank[i]]=w[i];
for(int h=a[1].h;h>=0;h--) {
ans[h]=ans[h+1]; cnt[h]=cnt[h+1];
for(;now<n && a[now].h==h;now++) {
x=a[now].id; y=x-1;
r1=find(x); r2=find(y);
ans[h]=max(ans[h],max(maxl[r1]*maxl[r2],minl[r1]*minl[r2]));
cnt[h]+=size[r1]*size[r2]; maxl[r2]=max(maxl[r2],maxl[r1]);
minl[r2]=min(minl[r2],minl[r1]);
size[r2]+=size[r1];
father[r1]=r2;
}
}
for(int i=0;i<n;i++) if(cnt[i]!=0) printf("%lld %lld\n",cnt[i],ans[i]); else printf("0 0\n");
} int main()
{
work();
return 0;
}
BZOJ4199/UOJ131 [Noi2015]品酒大会的更多相关文章
- 【BZOJ4199】[Noi2015]品酒大会 后缀数组+并查集
[BZOJ4199][Noi2015]品酒大会 题面:http://www.lydsy.com/JudgeOnline/wttl/thread.php?tid=2144 题解:听说能用SAM?SA默默 ...
- BZOJ4199:[NOI2015]品酒大会——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4199 https://www.luogu.org/problemnew/show/P2178#su ...
- 【bzoj4199】[Noi2015]品酒大会 后缀自动机求后缀树+树形dp
题目描述(转自百度文库) 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒 ...
- Bzoj4199:[NOI2015]品酒大会
题面 Bzoj4199 Sol 后缀数组 显然的暴力就是求\(LCP\)+差分 \(40\)分 # include <bits/stdc++.h> # define RG register ...
- 【BZOJ4199&UOJ131】品酒大会(后缀数组,并查集)
题意: 两杯“r相似” (r>1)的酒同时也是“1 相似”.“2 相似”.…….“(r−1) 相似”的. n<=300000 abs(a[i])<=10^9 思路:对于i,j两个后缀 ...
- UOJ131 [NOI2015] 品酒大会
考前挣扎(bu shi 之前留下来的坑 首先注意到 SAM的parent树 是反串的后缀树 也就是原串的前缀树 这个性质很重要 所以说我们在树上统计的时候两个点的lca就是两个后缀串的lcp 于是可以 ...
- bzoj4199: [Noi2015]品酒大会 (并查集 && 后缀数组)
据说用后缀自动机 + dp也能做 然而并不会 后缀数组的做法呢 就是先建个后缀数组,求出height值,此时如果直接找,复杂度是n ^ 2的,肯定会超时. 但是height大的值是不会对小的产生影响的 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
随机推荐
- cocos2d-x中关于touch事件的响应
原作者:有缘人 来源:新浪微博 地址:http://blog.sina.com.cn/s/blog_6ac2c7260102vvdu.html 一.touch事件响应分为单点触摸响应和多点触摸响应. ...
- GridView中给DropDownList动态绑定数据,及选择列表值后自动更新数据库
protected void sgvFile1_RowDataBound(object sender, GridViewRowEventArgs e) { DropDownList ddlAM = ( ...
- js对多行字符串的处理
f = [] g = str(f) h = ''.join(f) dic_ = () gd = str(dic_) hd = ''.join(dic_) 0 老板1 北京2 上海3 天津4 重庆5 河 ...
- Python 网络编程——socket
一 客户端/服务器架构 客户端(Client)服务器(Server)架构,即C/S架构,包括 1.硬件C/S架构(打印机) 2.软件C/S架构(web服务) 理想/目标状态—— 最常用的软件服务器是 ...
- (4.13)SQL Server profile使用、数据库优化引擎顾问使用
SQL Server profile使用技巧 介绍 经常会有人问profile工具该怎么使用?有没有方法获取性能差的sql的问题.自从转mysql我自己也差不多2年没有使用profile,忽然prof ...
- Slyce,这家硅谷创业公司的来头你知道吗
Slyce,也许你没听过,一家硅谷创业公司,旨在帮助运动员和其他社会名流组织.优化社交媒体,过滤粉丝的声音,让明星更好的在社交媒体上和他们互动.但是如果如果说库里,那你应该就知道了,拿到了上届NBA总 ...
- activiti部署到linux后流程图不显示汉字的问题
linux和windows的字体文件一般是不一样的,默认情况下,linux的java7中一般不支持中文,activiti的动态流程图中的汉字需要java调用汉字的字库,这里需要配置一下java的汉字字 ...
- pandas(零)数据结构
pandas的两个主要的数据结构: Series series是一种类似于一维数组的对象,它由一组数据(NumPy数组类型的数据)和一组与之相关的数据标签(索引)组成. from pandas imp ...
- LeetCode:搜索旋转排序数组【33】
LeetCode:搜索旋转排序数组[33] 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ...
- hive与hbase
作者:有点文链接:https://www.zhihu.com/question/21677041/answer/185664626来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...