当前位置: 首页 > news >正文

4199. [NOI2015]品酒大会【后缀数组+并查集】

Description

 一年一度的“幻影阁夏日品酒大会”隆重开幕了。大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品

酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加。在大会的晚餐上,调酒师Rainbow调制了 n 杯鸡尾酒。
这 n 杯鸡尾酒排成一行,其中第 i 杯酒 (1≤i≤n) 被贴上了一个标签 s_i ,每个标签都是 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) 相似”的。在品尝环节上,
品酒师Freda轻松地评定了每一杯酒的美味度,凭借其专业的水准和经验成功夺取了“首席品酒家”的称号,其中
第 i 杯酒 (1≤i≤n) 的美味度为 a_i 。现在Rainbow公布了挑战环节的问题:本次大会调制的鸡尾酒有一个特点
,如果把第 p 杯酒与第 q 杯酒调兑在一起,将得到一杯美味度为 a_p a_q 的酒。现在请各位品酒师分别对于 r=
0,1,2,?,n-1 ,统计出有多少种方法可以选出 2 杯“ r 相似”的酒,并回答选择 2 杯“ r 相似”的酒调兑可以
得到的美味度的最大值。

Input

输入文件的第1行包含1个正整数 n ,表示鸡尾酒的杯数。
第 2 行包含一个长度为 n 的字符串 S ,其中第 i 个字符表示第 i 杯酒的标签。
第 3 行包含 n 个整数,相邻整数之间用单个空格隔开,其中第 i 个整数表示第 i 杯酒的美味度 a_i 。
n=300,000 |a_i |≤1,000,000,000

Output

输出文件包括 n 行。第 i 行输出 2 个整数,中间用单个空格隔开。

第 1 个整数表示选出两杯“ (i-1)" " 相似”的酒的方案数,
第 2 个整数表示选出两杯“ (i-1) 相似”的酒调兑可以得到的最大美味度。
若不存在两杯“ (i-1) 相似”的酒,这两个数均为 0 。

Sample Input

10
ponoiiipoi
2 1 4 7 4 8 3 6 4 7

Sample Output

45 56
10 56
3 32
0 0
0 0
0 0
0 0
0 0
0 0
0 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 。

 

罕见的抄了一发题解……毕竟NOI原题哪有那么容易写出来的道理
并没有什么罕见的算法,不过思路还是很巧妙的
一开始我的想法是用单调栈,而且好像的确有这种算法的std,不过我乱搞了一下午样例都没过于是只好作罢
改为大众并查集做法。
首先很容易发现,对于任意一对r相似,它一定是k(0<k<r)相似的
所以求出height数组后按其中的值排序,然后从大到小做
当前需要处理的串为i和i-1,设前缀长度为k
易知若将两个并查集合并,则当前的前缀在并查集中一定是最小的,所以Ans[k][0]+=两棵树size的乘积(因为任意两两前缀都是k相似的,可以配对)
除了并查集的size,还维护一下并查集的max和min值,
则Ans[k][1]=max(Ans[k][1],Max1*Max2,Min1*Min2)
维护min值是为了防止有很小的复数这种情况(负负得正)
最后因为Ans[i]也是满足Ans[i+1]的,所以做个前缀和合并一下答案就好

 

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<algorithm>
  5 #define MAXN (300000+100)
  6 using namespace std;
  7 int wt[MAXN],wa[MAXN],wb[MAXN];
  8 int SA[MAXN],Rank[MAXN],Height[MAXN];
  9 char r[MAXN];
 10 int a[MAXN],cnt;
 11 int ID[MAXN],Father[MAXN];
 12 long long Size[MAXN],Max[MAXN],Min[MAXN],Ans[MAXN][2],INF;
 13 int n,m=130;
 14 
 15 bool cmp(int *y,int a,int b,int k)
 16 {
 17     int arank1=y[a];
 18     int brank1=y[b];
 19     int arank2=a+k>=n?-1:y[a+k];
 20     int brank2=b+k>=n?-1:y[b+k];
 21     return arank1==brank1 && arank2==brank2;
 22 } 
 23 
 24 void Build_SA()
 25 {
 26     int *x=wa,*y=wb;
 27     for (int i=0;i<m;++i) wt[i]=0;
 28     for (int i=0;i<n;++i) wt[x[i]=r[i]]++;
 29     for (int i=1;i<m;++i) wt[i]+=wt[i-1];
 30     for (int i=n-1;i>=0;--i) SA[--wt[x[i]]]=i;
 31     
 32     for (int j=1;j<=n;j<<=1)
 33     {
 34         int p=0;
 35         for (int i=n-j;i<n;++i) y[p++]=i;
 36         for (int i=0;i<n;++i) if (SA[i]>=j) y[p++]=SA[i]-j;
 37         
 38         for (int i=0;i<m;++i) wt[i]=0;
 39         for (int i=0;i<n;++i) wt[x[y[i]]]++;
 40         for (int i=1;i<m;++i) wt[i]+=wt[i-1];
 41         for (int i=n-1;i>=0;--i) SA[--wt[x[y[i]]]]=y[i];
 42         
 43         m=1;swap(x,y);
 44         x[SA[0]]=0;
 45         for (int i=1;i<n;++i)
 46             x[SA[i]]=cmp(y,SA[i],SA[i-1],j)?m-1:m++;
 47         if (m>=n) break;
 48     }
 49 }
 50 
 51 void Build_Height()
 52 {
 53     for (int i=0;i<n;++i) Rank[SA[i]]=i;
 54     int k=0;
 55     Height[0]=0;
 56     for (int i=0;i<n;++i)
 57     {
 58         if (!Rank[i]) continue;
 59         if (k) k--;
 60         int j=SA[Rank[i]-1];
 61         while (r[i+k]==r[j+k]) k++;
 62         Height[Rank[i]]=k;
 63     }
 64 }
 65 
 66 int Find (int x) {return Father[x]==x?x:Father[x]=Find(Father[x]);}
 67 void Merge (int x,int y)
 68 {
 69     int f1=Find(x),f2=Find(y);
 70     
 71     int k=Height[x];
 72     Ans[k][0]+=Size[f2]*Size[f1];
 73     Ans[k][1]=max(max(Max[f2]*Max[f1],Min[f2]*Min[f1]),Ans[k][1]);
 74     
 75     Min[f1]=min(Min[f1],Min[f2]);
 76     Max[f1]=max(Max[f1],Max[f2]);
 77     Father[f2]=f1;
 78     Size[f1]+=Size[f2];
 79 }
 80 
 81 void Solve()
 82 {
 83     for (int i=0;i<n;++i) 
 84     {
 85         Father[i]=i;
 86         Size[i]=1;
 87         Max[i]=Min[i]=a[SA[i]];
 88     }
 89     for (int i=0;i<=n-1;++i)
 90         if (Find(ID[i])!=Find(ID[i]-1))
 91             Merge(ID[i],ID[i]-1);
 92 }
 93 
 94 bool cmp1(int x,int y)
 95 {
 96     return Height[x]>Height[y];
 97 }
 98 
 99 int main()
100 {
101     memset(&INF,0x7f,sizeof(INF));
102     scanf("%d",&n);
103     scanf("%s",r);
104     for (int i=0;i<n;++i) 
105         scanf("%d",&a[i]);
106     Build_SA();
107     Build_Height();
108     for (int i=0;i<n;++i)
109     {
110         ID[i]=i;
111         Ans[i][0]=0;
112         Ans[i][1]=-INF;    
113     }
114     sort(ID,ID+n,cmp1);
115     Solve();
116     for (int i=n-2;i>=0;--i)
117     {
118         Ans[i][0]+=Ans[i+1][0];
119         Ans[i][1]=max(Ans[i][1],Ans[i+1][1]);
120     }
121     for (int i=0;i<n;++i)
122         printf("%lld %lld\n",Ans[i][0],Ans[i][0]==0?0:Ans[i][1]);
123 }

转载于:https://www.cnblogs.com/refun/p/8679198.html

相关文章:

  • 瞄准MSP市场风口,Bespin为企业转型保驾护航
  • 自己动手写CPU——寄存器堆、数据存储器(基于FPGA与Verilog)
  • OO1-3总结
  • nodejs使用log4js记录日志
  • WPF 自定义TextBox带水印控件,可设置圆角
  • SnapKit 最佳实践
  • Linux的磁盘配额
  • 【干货分享】SpringCloud微服务架构分布式组件如何共享session对象
  • 100. bootstrap 弹出对话框bootbox.confirm
  • jetty的使用
  • mysql架构
  • 详解node.js中的可读流(Readable)和可写流(Writeable)
  • 一文看懂JeffDean等提出的ENAS到底好在哪?
  • MXNet 作者李沐:用深度学习做图像分类,教程+代码
  • Map集合、散列表、红黑树介绍
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • mysql常用命令汇总
  • node-glob通配符
  • spring cloud gateway 源码解析(4)跨域问题处理
  • 百度地图API标注+时间轴组件
  • 第13期 DApp 榜单 :来,吃我这波安利
  • 基于Android乐音识别(2)
  • 前端技术周刊 2019-02-11 Serverless
  • 前端面试之CSS3新特性
  • 少走弯路,给Java 1~5 年程序员的建议
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​linux启动进程的方式
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • ​软考-高级-系统架构设计师教程(清华第2版)【第15章 面向服务架构设计理论与实践(P527~554)-思维导图】​
  • ​香农与信息论三大定律
  • ​油烟净化器电源安全,保障健康餐饮生活
  • !$boo在php中什么意思,php前戏
  • $L^p$ 调和函数恒为零
  • (0)Nginx 功能特性
  • (3)nginx 配置(nginx.conf)
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (JSP)EL——优化登录界面,获取对象,获取数据
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)Eureka服务搭建,服务注册,服务发现
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (排序详解之 堆排序)
  • (十八)用JAVA编写MP3解码器——迷你播放器
  • (一)Neo4j下载安装以及初次使用
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)创业家杂志:UCWEB天使第一步
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET Entity FrameWork 总结 ,在项目中用处个人感觉不大。适合初级用用,不涉及到与数据库通信。
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 中创建支持集合初始化器的类型
  • .net 逐行读取大文本文件_如何使用 Java 灵活读取 Excel 内容 ?
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)