【LOJ】#2133. 「NOI2015」品酒大会
题解
想出了一个神奇的技巧
我们先把串反过来(因为我们需要起始位置的值而不是终止位置的值),每个点维护一下 fail树上子树里的点,作为正数绝对值最大的两个数,作为负数绝对值最大的两个数
我们发现这个两两相乘的最大值肯定是一个后缀最大值,我们对每个节点求一个最大值存到这个节点的len处理出后缀最大值就行
然后关键是怎么求这个多少个位置两两匹配前缀是0,1,2....n - 1
似乎会想到把后缀自动机上节点的cnt累加进去就好?然而,这样是错的,你连第一个样例都过不了
为什么呢,我们把样例第一个串反过来之后看一看
ponoiiipoi
iopiiionop
你如果要统计两个p的位置作为相同长度为1的两个位置
非常尴尬,没有这个节点
怎么办,你BFS显然会超时……为什么i这个位置就会被统计进去……因为有这个节点
ii这个节点的par就是i
经过一番大胆的猜想,发现我们需要把\([p->par->len + 1,p->len]\)这一段的答案要加上\(p->cnt *(p->cnt - 1) / 2\)
那么为什么这样是正确的呢……显然= =
因为p->par就是p的一段后缀,这段后缀显然会累加上由于最长匹配是个长串带来的贡献,而中间的一段也是这个长串的一部分,没有被加上
代码
#include <bits/stdc++.h>
//#define ivorysi
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eps 1e-8
#define mo 974711
#define MAXN 300005
#define pii pair<int,int>
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int len,cnt;
int val[2][2],vc[2];
node *nxt[26],*par;
}pool[MAXN * 2],*tail = pool,*root,*last,*que[MAXN * 2];
int a[MAXN],N,c[MAXN];
int64 ans[MAXN],sum[MAXN],d[MAXN];
char str[MAXN];
void build_SAM(int e,int len,int v) {
node *nowp = tail++,*p;
nowp->len = len;nowp->cnt = 1;
if(v < 0) nowp->val[0][nowp->vc[0]++] = v;
else nowp->val[1][nowp->vc[1]++] = v;
for(p = last ; p && !p->nxt[e] ; p = p->par) {
p->nxt[e] = nowp;
}
if(!p) nowp->par = root;
else {
node *q = p->nxt[e];
if(q->len == p->len + 1) nowp->par = q;
else {
node *copyq = tail++;
*copyq = *q;
copyq->vc[0] = copyq->vc[1] = 0;
memset(copyq->val,0,sizeof(copyq->val));
copyq->cnt = 0;
copyq->len = p->len + 1;
q->par = nowp->par = copyq;
for(; p && p->nxt[e] == q ; p = p->par) p->nxt[e] = copyq;
}
}
last = nowp;
}
void update(node *p,int on,int v) {
if(p->vc[on] < 2) {p->val[on][1] = v;++p->vc[on];}
else {
if(abs(v) > abs(p->val[on][1])) p->val[on][1] = v;
}
if(abs(p->val[on][1]) > abs(p->val[on][0])) swap(p->val[on][1],p->val[on][0]);
}
void Init() {
read(N);scanf("%s",str + 1);
for(int i = 1 ; i <= N ; ++i) read(a[i]);
for(int i = 1 ; i <= N / 2 ; ++i) {
swap(a[i],a[N - i + 1]);swap(str[i],str[N - i + 1]);
}
root = last = tail++;
for(int i = 1 ; i <= N ; ++i) build_SAM(str[i] - 'a',i,a[i]);
}
void Solve() {
int m = tail - pool;
for(int i = 0 ; i < m ; ++i) c[pool[i].len]++;
for(int i = 1 ; i <= N ; ++i) c[i] += c[i - 1];
for(int i = 0 ; i < m ; ++i) que[c[pool[i].len]--] = &pool[i];
for(int i = 0 ; i <= N ; ++i) ans[i] = -1e18;
for(int i = m ; i >= 1 ; --i) {
if(que[i]->cnt > 1) {
sum[que[i]->len] += 1LL * (que[i]->cnt - 1) * (que[i]->cnt) / 2;
if(que[i]->vc[0] >= 2) ans[que[i]->len] = max(ans[que[i]->len],1LL * que[i]->val[0][1] * que[i]->val[0][0]);
if(que[i]->vc[1] >= 2) ans[que[i]->len] = max(ans[que[i]->len],1LL * que[i]->val[1][0] * que[i]->val[1][1]);
for(int k = 0 ;k < que[i]->vc[0] ; ++k) {
for(int h = 0 ; h < que[i]->vc[1] ; ++h) {
ans[que[i]->len] = max(ans[que[i]->len],1LL * que[i]->val[0][k] * que[i]->val[1][h]);
}
}
}
d[que[i]->len - 1] += 1LL * (que[i]->cnt - 1) * que[i]->cnt / 2;
if(que[i]->par) {
que[i]->par->cnt += que[i]->cnt;
for(int k = 0 ; k < que[i]->vc[0] ; ++k) {
update(que[i]->par,0,que[i]->val[0][k]);
}
for(int k = 0 ; k < que[i]->vc[1] ; ++k) {
update(que[i]->par,1,que[i]->val[1][k]);
}
d[que[i]->par->len] -= 1LL * (que[i]->cnt - 1) * que[i]->cnt / 2;
}
}
for(int i = N ; i >= 1 ; --i) d[i] += d[i + 1],sum[i] += d[i];
for(int i = N - 1; i >= 1 ; --i) ans[i] = max(ans[i + 1],ans[i]);
for(int i = 0 ; i <= N - 1 ; ++i) {
if(!sum[i]) ans[i] = 0;
out(sum[i]);space;out(ans[i]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
【LOJ】#2133. 「NOI2015」品酒大会的更多相关文章
- loj#2129. 「NOI2015」程序自动分析
题目链接 loj#2129. 「NOI2015」程序自动分析 题解 额... 考你会不会离散化优化常数 代码 #include<queue> #include<cstdio> ...
- *LOJ#2134. 「NOI2015」小园丁与老司机
$n \leq 5e4$个平面上的点,从原点出发,能从当前点向左.右.上.左上或右上到达该方向最近的给定点.问三个问:一.最多经过多少点:二.前一问的方案:三.其所有方案种非左右走的边至少要开几辆挖掘 ...
- LOJ#2132. 「NOI2015」荷马史诗
$n \leq 100000$个数字,放进$k$叉树里,一个点只能放一个数,使所有数字乘以各自深度这个值之和最小的同时,最大深度的数字最小. 哈夫曼.这是我刚学OI那段时间看到的,感觉就是个很无聊的贪 ...
- LOJ#2131. 「NOI2015」寿司晚宴
$n \leq 500$,$2-n$这些数字,两个人挑,可以重复挑,问有几种方案中,一个人选的所有数字与另一个人选的所有数字都互质. 不像前两题那么抠脚.. 如果$n$比较小的话,可以把两个人选的数字 ...
- Uoj #131. 【NOI2015】品酒大会 后缀数组,并查集
#131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...
- 【BZOJ4199】【NOI2015】品酒大会(后缀数组)
[BZOJ4199][NOI2015]品酒大会 题面 BZOJ Uoj 洛谷 题解 考虑最裸的暴力 枚举每次的长度 以及两个开始的位置 检查以下是否满足条件,如果可以直接更新答案 复杂度\(O(n^3 ...
- Loj #2192. 「SHOI2014」概率充电器
Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...
- Loj #3096. 「SNOI2019」数论
Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...
- Loj #3093. 「BJOI2019」光线
Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...
随机推荐
- vue添加属性绑定
html <div id="app-2"> <span v-bind:title="message"> 鼠标悬停几秒钟查看此处动态绑定的 ...
- Linux常用网络工具:hping高级主机扫描
之前介绍了主机扫描工具fping,可以参考我写的<Linux常用网络工具:fping主机扫描>. hping是一款更高级的主机扫描工具,它支持TCP/IP数据包构造.分析,在某些防火墙配置 ...
- python基础6--目录结构
为什么要设计好目录结构? "设计项目目录结构",就和"代码编码风格"一样,属于个人风格问题.对于这种风格上的规范,一直都存在两种态度: 一类同学认为,这种个人风 ...
- [LeetCode] Gas Station,转化为求最大序列的解法,和更简单简单的Jump解法。
LeetCode上 Gas Station是比较经典的一题,它的魅力在于算法足够优秀的情况下,代码可以简化到非常简洁的程度. 原题如下 Gas Station There are N gas stat ...
- [LeetCode] 30. Substring with Concatenation of All Words ☆☆☆
You are given a string, s, and a list of words, words, that are all of the same length. Find all sta ...
- 2015/9/29 Python基础(20):类的授权
类的授权 1.包装包装在Python编程世界中时经常会被提到的一个术语.它是一个通用的名字,意思是对一个已存在的对象进行包装,不管它是数据类型,还是一段代码,可以是对一个已存在的对象,增加新的,删除不 ...
- JAVA多线程提高十一:同步工具Exchanger
Exchanger可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchange 方法,与伙伴线程进行匹配,并且在返回时接收其伙伴的对象.Exchanger 可能被视 ...
- 【BZOJ】1597 [Usaco2008 Mar]土地购买
[算法]DP+斜率优化 [题意]n(n≤50000)块土地,长ai宽bi,可分组购买,每组代价为max(ai)*max(bi),求最小代价. [题解] 斜率优化:http://www.cnblogs. ...
- NSURLSession---iOS-Apple苹果官方文档翻译
CHENYILONG Blog NSURLSession---iOS-Apple苹果官方文档翻译 NSURLSession 技术博客http://www.cnblogs.com/ChenYilong/ ...
- python学习笔记(十二)之函数
牛刀小试: 定义一个无参函数 >>> def myFirstFunc(): ... print("Hello python") ... print("h ...