品酒大会

【问题描述】

【输入格式】

【输出格式】

【样例输入】

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

【样例输出】

45 56
10 56
3 32
0 0
0 0
0 0
0 0
0 0
0 0
0 0

【数据范围】


题解:

根据题意可得"r相似”也是“r - 1相似”

那么我们只要求出了所有最大为 r 相似的对数,就可以利用后缀和求出所有r相似的个数

考虑一瓶酒与另一瓶酒如果是 r 相似的,那么与其中一瓶酒 k (k > r) 相似的酒与另一瓶酒最大也为 r 相似

所以用后缀数组求出 height 数组

然后按 height 从大到小排序

每次按顺序找出两个 height 相似的点的祖先

height 相似的对数累加上两个祖先块内的点数乘积

height 相似的最大值为两个块的最小值乘积和最大值乘积的较大值

用并查集合并,处理点的个数、最大值和最小值(美味度有负数)

最后跑一遍后缀和

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
inline void Scan(int &x)
{
char c;
int o = ;
while((c = getchar()) < '' || c > '')
if(c == '-') o = -;
x = c - '';
while((c = getchar()) >= '' && c <= '') x = x * + c - '';
x *= o;
}
const int me = ;
int n;
int w[me];
int x[me];
int sa[me], he[me];
int val[me], fat[me], nex[me];
int rank[me];
long long ans_si[me], ans_mx[me];
char s[me];
struct Union
{
long long si, mx, mi;
};
Union un[me];
inline void Sa()
{
int m = ;
for(int i = ; i <= n; ++i) ++w[x[i] = s[i] - 'a' + ];
for(int i = ; i <= m; ++i) w[i] += w[i - ];
for(int i = n; i >= ; --i) sa[w[x[i]]--] = i;
for(int k = ; k <= n; k <<= )
{
int p = ;
for(int i = n; i >= n - k + ; --i) rank[++p] = i;
for(int i = ; i <= n; ++i)
if(sa[i] > k)
rank[++p] = sa[i] - k;
for(int i = ; i <= m; ++i) w[i] = ;
for(int i = ; i <= n; ++i) ++w[x[i]];
for(int i = ; i <= m; ++i) w[i] += w[i - ];
for(int i = n; i >= ; --i) sa[w[x[rank[i]]]--] = rank[i];
m = ;
for(int i = ; i <= n; ++i)
{
int u = sa[i], v = sa[i - ];
if(x[u] != x[v] || x[u + k] != x[v + k]) rank[u] = ++m;
else rank[u] = m;
}
if(n == m) break;
for(int i = ; i <= n; ++i) swap(x[i], rank[i]);
}
int tot = ;
int i, j;
for(i = ; i <= n; i ++)
{
if (tot) tot --;
j = sa[rank[i] - ];
while (s[j + tot] == s[i + tot]) tot ++;
he[rank[i]] = tot;
}
}
inline bool rule(const int &x, const int &y)
{
return he[x] > he[y];
}
inline int Find(const int &x)
{
return (x != fat[x]) ? fat[x] = Find(fat[x]) : x;
}
inline void Un(const int &x, const int &y)
{
un[x].si += un[y].si;
un[x].mx = max(un[x].mx, un[y].mx);
un[x].mi = min(un[x].mi, un[y].mi);
fat[y] = x;
}
int main()
{
Scan(n);
scanf("%s", s + );
for(int i = ; i <= n; ++i)
{
Scan(val[i]);
nex[i] = i + ;
fat[i] = i;
}
Sa();
for(int i = ; i <= n; ++i)
ans_mx[i] = -;
for(int i = ; i <= n; ++i)
un[i] = (Union) {, val[sa[i]], val[sa[i]]};
sort(nex + , nex + n, rule);
for(int i = ; i < n; ++i)
{
int x = Find(nex[i] - ), y = Find(nex[i]);
int z = he[nex[i]];
ans_si[z] += un[x].si * un[y].si;
ans_mx[z] = max(ans_mx[z], max(un[x].mi * un[y].mi, un[x].mx * un[y].mx));
Un(x, y);
}
for(int i = n - ; i >= ; --i)
{
ans_si[i] += ans_si[i + ];
ans_mx[i] = max(ans_mx[i], ans_mx[i + ]);
}
for(int i = ; i < n; ++i)
printf("%lld %lld\n", ans_si[i], ans_si[i] ? ans_mx[i] : );
}

品酒大会 BZOJ 4199的更多相关文章

  1. [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会

    [LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会 题意 给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\ ...

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

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

  3. [BZOJ]4199 品酒大会(Noi2015)

    讲道理是后缀数组裸题吧,虽然知道后缀数组的原理但是小C不会写是什么鬼.. 小C趁着做这题的当儿,学习了一下后缀数组. 网络上的后缀数组模板完全看不懂怎么破,全程照着黄学长的代码抄,感觉黄学长写得还是很 ...

  4. bzoj 4199 && NOI 2015 品酒大会

    一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 ...

  5. bzoj 4199: [Noi2015]品酒大会

    Description 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品酒家"和"首席猎手&quo ...

  6. 【刷题】BZOJ 4199 [Noi2015]品酒大会

    Description 一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品酒家"和"首席猎手&quo ...

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

    Description 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加.在大会的晚餐上,调酒师 ...

  8. 【BZOJ-4199】品酒大会 后缀数组 + 并查集合并集合

    4199: [Noi2015]品酒大会 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 436  Solved: 243[Submit][Status] ...

  9. 【BZOJ4199】【NOI2015】品酒大会(后缀数组)

    [BZOJ4199][NOI2015]品酒大会 题面 BZOJ Uoj 洛谷 题解 考虑最裸的暴力 枚举每次的长度 以及两个开始的位置 检查以下是否满足条件,如果可以直接更新答案 复杂度\(O(n^3 ...

随机推荐

  1. strongSwan大坑一直重启(ubuntu)

    报错 Starting strongSwan 5.3.2 IPsec [starter]... charon (20533) started after 40 ms charon stopped af ...

  2. Cayley凯莱定理——一一对应

    定理 过$n$个有标志顶点的树的数目等于$n^{n-2}$. 此定理说明用$n-1$条边将$n$个已知的顶点连接起来的连通图的个数是$n^{n-1}$.也可以这样理解,将n个城市连接起来的树状网络有$ ...

  3. js获取当前日期、前一天、后一天的日期的例子

    <script> function addByTransDate(dateParameter, num) { var translateDate = "", dateS ...

  4. end和sep的使用方法

    end: 默认是换行'\n',表示以什么结尾,比如以, | \n 等 方法: 默认end = '\n' a b c 如果end = ' ' a b c sep: 默认是空格' ' 表示两个字符之间用什 ...

  5. Bootstrap历练实例:基本按钮群组

    <!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...

  6. 【二分 贪心】bzoj3477: [Usaco2014 Mar]Sabotage

    科学二分姿势 Description Farmer John's arch-nemesis, Farmer Paul, has decided to sabotage Farmer John's mi ...

  7. CentOS7.5下开发systemctl管理的自定义Nginx启动服务程序

    一.systemctl知识简介 从CentOS7 Linux开始,系统里的网络服务启动已经从传统的service改成了systemctl(一个systemd工具,主要负责控制systemd系统和服务管 ...

  8. 数据结构( Pyhon 语言描述 ) — — 第8章:队列

    队列概览 队列是线性的集合 队列的插入限制在队尾,删除限制在队头.支持先进先出协议( FIFIO, first-in first-out ) 两个基本操作 add:在队尾添加一项 pop:从队头弹出一 ...

  9. LeetCode(72) Edit Distance

    题目 Given two words word1 and word2, find the minimum number of steps required to convert word1 to wo ...

  10. 基础训练 FJ的字符串

    FJ的字符串 #include<iostream> #include<string.h> using namespace std; int main(){ string str ...