bzoj4199: [Noi2015]品酒大会 (并查集 && 后缀数组)
据说用后缀自动机 + dp也能做
然而并不会
后缀数组的做法呢
就是先建个后缀数组,求出height值,此时如果直接找,复杂度是n ^ 2的,肯定会超时。
但是height大的值是不会对小的产生影响的,所以可以按height大小,从大到小合并两个区间,用并查集维护就可以了
代码如下
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = ;
typedef long long ll;
char s[N];
ll a[N];
int n;
int sa[N], c[N], x[N], y[N]; struct E {
int h, l, r;
inline bool operator < (const E o) const {
return h > o.h;
}
} g[N];
inline void BuildSa(int m) {
for (int i = ; i < m; i++) c[i] = ;
for (int i = ; i < n; i++) c[x[i] = s[i]]++;
for (int i = ; i < m; i++) c[i] += c[i - ];
for (int i = n - ; i >= ; i--) sa[--c[x[i]]] = i;
for (int k = ; k <= n; k <<= ) {
int p = ;
for (int i = n - k; i < n; i++) y[p++] = i;
for (int i = ; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k;
for (int i = ; i < m; i++) c[i] = ;
for (int i = ; i < n; i++) c[x[y[i]]]++;
for (int i = ; i < m; i++) c[i] += c[i - ];
for (int i = n - ; i >= ; i--) sa[--c[x[y[i]]]] = y[i];
p = ; swap(x, y);
x[sa[]] = ;
for (int i = ; i < n; i++)
x[sa[i]] = y[sa[i]] == y[sa[i - ]] && y[sa[i] + k] == y[sa[i - ] + k] ? p - : p++;
if (p >= n) break;
m = p;
}
} int height[N], rank[N];
inline void GetHeight() {
for (int i = ; i < n; i++) rank[sa[i]] = i;
int k = ;
for (int i = ; i < n; i++) {
if (k) k--;
int j = sa[rank[i] - ];
while (s[j + k] == s[i + k]) k++;
height[rank[i]] = k;
}
} ll fa[N], size[N], ans[N], ans1[N], ans2[N], minn[N], maxn[N];
void Union(int x, int y) {
fa[x] = y;
size[y] += size[x];
ans[y] = max(ans[y], max(maxn[y] * maxn[x], minn[y] * minn[x]));
maxn[y] = max(maxn[y], maxn[x]);
minn[y] = min(minn[y], minn[x]);
} int find(int x) {
return (fa[x] == x) ? x : find(fa[x]);
} int main() {
scanf("%d", &n);
getchar();
for (int i = ; i < n; i++)
scanf("%c", &s[i]), s[i] -= 'a' - ;
for (int i = ; i < n; i++)
scanf("%lld", &a[i]);
s[n++] = ;
BuildSa();
GetHeight();
for (int i = ; i < n; i++) {
g[i].h = height[i];
g[i].l = sa[i];
g[i].r = sa[i - ];
}
sort(g + , g + n);
for (int i = ; i < n; i++) fa[i] = i, size[i] = , maxn[i] = a[i], minn[i] = a[i];
memset(ans, 0x80, sizeof(ans));
memset(ans2, 0x80, sizeof(ans2));
for (int i = ; i < n; i++) {
int x = find(g[i].l);
int y = find(g[i].r);
ans1[g[i].h] += (ll)size[x] * size[y];
Union(x, y);
ans2[g[i].h] = max(ans2[g[i].h], ans[y]);
}
for (int i = n - ; i >= ; i--) {
ans1[i] += ans1[i + ];
if (ans1[i + ]) ans2[i] = max(ans2[i], ans2[i + ]);
}
for (int i = ; i < n - ; i++) printf("%lld %lld\n", ans1[i], ans1[i] ? ans2[i] : );
return ;
}
bzoj4199: [Noi2015]品酒大会 (并查集 && 后缀数组)的更多相关文章
- [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- [UOJ#131][BZOJ4199][NOI2015]品酒大会
[UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...
- bzoj4199: [Noi2015]品酒大会(后缀数组)
题目描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战 两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainb ...
- [bzoj4199][Noi2015]品酒大会_后缀自动机_后缀树_树形dp
品酒大会 bzoj-4199 Noi-2015 题目大意:给定一个字符串,如果其两个子串的前$r$个字符相等,那么称这两个子串的开头两个位置$r$相似.如果两个位置勾兑在一起那么美味度为两个位置的乘积 ...
- BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】
题目 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品 酒家"和"首席猎手"两个奖项,吸 ...
- [BZOJ4199][NOI2015]品酒大会
#131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...
- 并不对劲的bzoj4199: [Noi2015]品酒大会
传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...
- bzoj千题计划257:bzoj4199: [Noi2015]品酒大会
http://www.lydsy.com/JudgeOnline/problem.php?id=4199 求出后缀数组的height 从大到小枚举,合并 维护组内 元素个数,最大.次大.最小.次小 # ...
- [BZOJ4199][Noi2015]品酒大会 树形DP+后缀自动机
由于要找后缀的前缀,所以先用反串建立SAM. link边组成了后缀树. 两个子串的最长公共前缀是LCA的step 树形dp即可. #include<iostream> #include&l ...
随机推荐
- Java课后总结-原码、补码、反码
1.原码.补码.反码的定义和表示方法. 数在计算机中是以二进制形式表示的. 数分为有符号数和无符号数. 原码.反码.补码都是有符号定点数的表示方法. 一个有符号定点数的最高位为符号位,0是正,1是副. ...
- hdu6212 Zuma(区间dp)
#pragma GCC optimize(2) #include <bits/stdc++.h> #define ll long long #define ls(i) i<<1 ...
- 关于Java8中的Comparator那些事
在前面一篇博文中,对于java中的排序方法进行比较和具体剖析,主要是针对 Comparator接口和 Comparable接口,无论是哪种方式,都需要实现这个接口,并且重写里面的 方法.Java8中对 ...
- 6.Docker Compose 网络设置
概述 默认情况下,Compose 会为我们的应用创建一个网络,服务的每个容器都会加入该网络中.这样,容器就可被该网络中的其他容器访问,不仅如此,该容器还能以服务名称作为 Hostname 被其他容器访 ...
- 原生JS操作class 极致版
// 获取class function getClass(el) { return el.getAttribute('class') } // 设置class function setClass(el ...
- source insight增加tab标签页的方法之sihook
1.效果如下 2.方法见如下博客 http://www.cnblogs.com/Red_angelX/archive/2013/01/23/2873603.html
- Jmeter-第三方插件安装
1.插件下载 官方地址https://jmeter-plugins.org/install/Install/ 网盘地址链接: https://pan.baidu.com/s/1E4lnMWDGPWCN ...
- C语言库函数strstr、strch比较
该库函数包含在<string.h>头文件中,函数原型:extern char *strstr(char *str1, const char *str2);使用方法 char *strstr ...
- lampp ERROR 1044 (42000): Access denied for user ''@'localhost' to database 'lepus'
解决方法: 在[mysqlld]段下增加如下代码:skip-grant-tables: 1.which mysql 查看mysql位置,例如:/opt/lampp/bin/mysql 2.进入配置my ...
- url 获取 geoserver 中对应的style
http://userName:password@127.0.0.1:7093/geoserver/rest/workspaces/FAST/styles/AVG_RSRP.sld