求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N))

-----------------------------------------------------------------------------------

#include<cstdio>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
typedef long long ll;
 
const ll INF = -1LL << 60;
const int maxn = 300009;
 
char S[maxn];
int w[maxn], N;
int cnt[maxn], Sa[maxn], Rank[maxn], Height[maxn];
int mx[maxn], mn[maxn], fa[maxn], sz[maxn], r[maxn];
ll ans[maxn], tot[maxn];
 
void Init() {
scanf("%d%s", &N, S);
for(int i = 0; i < N; i++) scanf("%d", w + i);
S[N++] = '$';
}
 
void Build() {
int m = 255, *x = Height, *y = Rank;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[i]]] = i;
for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) {
for(int i = N - k; i < N; i++) y[p++] = i;
for(int i = 0; i < N; i++)
if(Sa[i] >= k) y[p++] = Sa[i] - k;
for(int i = 0; i < m; i++) cnt[i] = 0;
for(int i = 0; i < N; i++) cnt[x[y[i]]]++;
for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];
for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i];
swap(x, y), x[Sa[0]] = 0, p = 1;
for(int i = 1; i < N; i++) {
if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++;
x[Sa[i]] = p - 1;
}
if((m = p) >= N) break;
}
for(int i = 0; i < N; i++) Rank[Sa[i]] = i;
Height[0] = 0;
for(int i = 0, h = 0; i < N; i++) if(Rank[i]) {
if(h) h--;
while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++;
Height[Rank[i]] = h;
}
}
 
int Find(int x) {
return x == fa[x] ? x : fa[x] = Find(fa[x]);
}
 
bool Cmp(const int &l, const int &r) {
return Height[l] > Height[r];
}
 
inline void Max(ll &x, ll t) {
if(t > x) x = t;
}
inline void Max(int &x, int t) {
if(t > x) x = t;
}
inline void Min(int &x, int t) {
if(t < x) x = t;
}
 
void Work() {
for(int i = 0; i < N; i++) {
sz[i] = 1;
r[i] = fa[i] = i;
mx[i] = mn[i] = w[i];
tot[i] = 0;
ans[i] = INF;
}
sort(r, r + N, Cmp);
for(int i = 0; i < N; i++) if(r[i] > 1) {
int u = Find(Sa[r[i]]), v = Find(Sa[r[i] - 1]);
if(u == v) continue;
tot[Height[r[i]]] += ll(sz[u]) * sz[v];
Max(ans[Height[r[i]]], max(ll(mx[u]) * mx[v], ll(mn[u]) * mn[v]));
fa[u] = v, sz[v] += sz[u];
Max(mx[v], mx[u]);
Min(mn[v], mn[u]);
}
for(int i = Height[r[0]]; i--; )
tot[i] += tot[i + 1], Max(ans[i], ans[i + 1]);
for(int i = 0; i + 1 < N; i++)
printf("%lld %lld\n", tot[i], ans[i] != INF ? ans[i] : 0);
}
 
int main() {
Init();
Build();
Work();
return 0;
}

-----------------------------------------------------------------------------------

BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )的更多相关文章

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

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

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

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

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

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

  4. [NOI2015] 品酒大会 - 后缀数组,并查集,STL,启发式合并

    [NOI2015] 品酒大会 Description 对于每一个 \(i \in [0,n)\) 求有多少对后缀满足 LCP 长度 \(\le i\) ,并求满足条件的两个后缀权值乘积的最大值. So ...

  5. BZOJ.4199.[NOI2015]品酒大会(后缀数组 单调栈)

    BZOJ 洛谷 后缀自动机做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 显然只需要考虑极长的相同子串的贡献,然后求后缀和/后缀\(\max\)就可以了. 对于相同子串,我们能想 ...

  6. 【学术篇】NOI2015 品酒大会 后缀数组+并查集

    省选前大致是刷不了几道题了... 所以就找一些裸一点的题目练练板子算了= = 然而这题一点都不裸, 也并不怎么好写... 于是就浪费了将近一下午的时间... 然而还不是因为后缀数组板子不熟= = 首先 ...

  7. NOI 2015 品酒大会 (后缀数组+并查集)

    题目大意:略 40分暴力还是很好写的,差分再跑个后缀和 和 后缀最大值就行了 一种正解是后缀数组+并查集 但据说还有后缀数组+单调栈的高端操作蒟蒻的我当然不会 后缀数组求出height,然后从大到小排 ...

  8. BZOJ.4199.[NOI2015]品酒大会(后缀自动机 树形DP)

    BZOJ 洛谷 后缀数组做法. 洛谷上SAM比SA慢...BZOJ SAM却能快近一倍... 只考虑求极长相同子串,即所有后缀之间的LCP. 而后缀的LCP在后缀树的LCA处.同差异这道题,在每个点处 ...

  9. Uoj #131. 【NOI2015】品酒大会 后缀数组,并查集

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

随机推荐

  1. 采用OSChina代码托管管理项目(一)

    .Git是什么 Git在Wikipedia上的定义:它是一个免费的.分布式的版本号控制工具,或是一个强调了速度快的源码管理工具. Git最初被Linus Torvalds开发出来用于管理Linux内核 ...

  2. Android入门——UI(8)——Fragment(2)

    先演示一下如何在一个activity中放置两个Fragment,先定义两个Fragment <?xml version="1.0" encoding="utf-8& ...

  3. Check SMTP Server Availability for ORA-29278 or ORA-29279 errors using UTL_SMTP to Send Email

    Check SMTP Server Availability for ORA-29278 or ORA-29279 errors using UTL_SMTP to Send Email. (文档 I ...

  4. 轻量级的数据交换语言(JSON)

    游戏开发过程中,很多用到JSON的地方:客户端与服务端的网络通信,程序读取客户端的数值表之类的. JSON用于描述数据结构,有以下形式存在. 对象(object):一个对象以“{”开始,并以“}”结束 ...

  5. Qt QtableView使用

    ui->setupUi(this); ui->mainToolBar->hide(); tableView = new QTableView(this); // 设置表头 QStan ...

  6. .Xmodmap vim键位映射。

    remove Lock = Caps_Lockkeysym Caps_Lock = Control_Ladd Control = Control_Lkeysym Escape = grave asci ...

  7. http request parameter

    http request parameter add htmlspecialchars host?vendor_id=1000000&q=Some%20children%20wish%20to ...

  8. js previousSibling兼容使用方法

    使用previousSibling的时候发现当前元素跟上一个元素之间有空格就不获取不到对象, 查资料才知道除了ie外js的previousSibling获取的对象包括空格! 兼容方法如下: funct ...

  9. css3 transform 变形

    在css3中,用transform可以实现文字或图像的旋转.缩放.倾斜和移动,并且该元素下的所有子元素,随着父元素一样转.缩放.倾斜和移动. transform属性 transform的属性包括:ro ...

  10. caffe 配置 札记

    cudnn的配置 1. 安装前请去先官网下载cuDNN (cudnn-7.0-linux-x64-v3),建议安装v3,v4有些问题. 将cudnn-7.0-linux-x64-v3解压后会有两个文件 ...