[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会
[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会
题意
给定一个长度为 \(n\) 的字符串 \(s\), 对于所有 \(r\in[1,n]\) 求出 \(s\) 的所有LCP不小于 \(r\) 的后缀对的个数以及这些后缀对所能组成的最大权值.
一个后缀对 \((a,b)\) 的权值是它们左端点的权值的积.
\(n\le 3\times 10^5\).
题解
很久以前写的SAM沙雕题
因为要求LCP所以我们把这个串reverse一下用SAM搞.
根据后缀自动机的性质, 某两个后缀的LCP就是它们在SAM上对应结点的LCA的 \(len\).
那么对于计数的部分, 我们显然只要对于每个点都算出有多少个后缀以它为LCA就可以了.
后面求最大权值的部分看上去好像只要记录一下子树中的最大值和次大值就可以了, 然而权值可能有负数于是还得记录最小值和次小值.
计算出每个 \(len\) 的贡献后取后缀和就可以出答案了.
参考代码
#include <bits/stdc++.h>
const int MAXN=6e5+10;
typedef long long int64;
struct Edge{
int from;
int to;
Edge* next;
};
Edge E[MAXN];
Edge* head[MAXN];
Edge* top=E;
int n;
int cnt=1;
int root=1;
int last=1;
int v[MAXN];
char s[MAXN];
int len[MAXN];
int prt[MAXN];
int val[MAXN];
int size[MAXN];
int64 ans[MAXN];
int64 sum[MAXN];
int maxv[MAXN][2];
int minv[MAXN][2];
std::map<char,int> chd[MAXN];
void DFS(int);
void Insert(int,int);
void Extend(char,int);
int main(){
memset(ans,0x80,sizeof(ans));
memset(maxv,0x80,sizeof(maxv));
memset(minv,0x7F,sizeof(minv));
scanf("%d",&n);
scanf("%s",s);
for(int i=0;i<n;i++)
scanf("%d",v+i);
for(int i=1;i<=n;i++)
Extend(s[n-i],v[n-i]);
for(int i=2;i<=cnt;i++)
Insert(prt[i],i);
DFS(root);
for(int i=n-1;i>=0;i--){
sum[i]+=sum[i+1];
ans[i]=std::max(ans[i],ans[i+1]);
}
for(int i=0;i<n;i++)
printf("%lld %lld\n",sum[i],sum[i]==0?0:ans[i]);
return 0;
}
void UpdateMax(int x,int v){
maxv[x][1]=std::max(maxv[x][1],v);;
if(maxv[x][0]<maxv[x][1])
std::swap(maxv[x][0],maxv[x][1]);
}
void UpdateMin(int x,int v){
minv[x][1]=std::min(minv[x][1],v);
if(minv[x][0]>minv[x][1])
std::swap(minv[x][0],minv[x][1]);
}
void DFS(int root){
for(Edge* i=head[root];i!=NULL;i=i->next){
DFS(i->to);
sum[len[root]]+=1ll*size[root]*size[i->to];
size[root]+=size[i->to];
UpdateMin(root,minv[i->to][0]);
UpdateMin(root,minv[i->to][1]);
UpdateMax(root,maxv[i->to][0]);
UpdateMax(root,maxv[i->to][1]);
}
if(size[root]>1)
ans[len[root]]=std::max(ans[len[root]],std::max(1ll*minv[root][0]*minv[root][1],1ll*maxv[root][0]*maxv[root][1]));
}
void Extend(char x,int v){
int p=last;
int np=++cnt;
size[last=np]=1;
len[np]=len[p]+1;
minv[np][0]=v;
maxv[np][0]=v;
while(p&&!chd[p].count(x))
chd[p][x]=np,p=prt[p];
if(p==0)
prt[np]=root;
else{
int q=chd[p][x];
if(len[q]==len[p]+1)
prt[np]=q;
else{
int nq=++cnt;
chd[nq]=chd[q];
prt[nq]=prt[q];
prt[q]=nq;
prt[np]=nq;
len[nq]=len[p]+1;
while(p&&chd[p][x]==q)
chd[p][x]=nq,p=prt[p];
}
}
}
void Insert(int from,int to){
top->from=from;
top->to=to;
top->next=head[from];
head[from]=top++;
}
[LOJ 2133][UOJ 131][BZOJ 4199][NOI 2015]品酒大会的更多相关文章
- bzoj 4199 && NOI 2015 品酒大会
一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 ...
- [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机
[LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机 题意 给定平面上的 \(n\) 个整点 \((x_i,y_i)\), 一共有两个问题. 第一个问题是从原 ...
- [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程
[LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程 题意 给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 ...
- [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分
[LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...
- [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士
[LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...
- UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)
水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.org/problemnew/show/P2178 https://www.lydsy.com/JudgeOnline ...
- 【UOJ #131】【NOI 2015】品酒大会
http://uoj.ac/problem/131 求出后缀数组和height数组后,从大到小扫相似度进行合并,每次相当于合并两个紧挨着的区间. 合并区间可以用并查集来实现,每个区间的信息都记录在这个 ...
- uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d
题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...
- [NOI 2015]品酒大会
Description 题库链接 \(n\) 杯鸡尾酒排成一行,其中第 \(i\) 杯酒 (\(1 \leq i \leq n\)) 被贴上了一个标签 \(s_i\),每个标签都是 \(26\) 个小 ...
随机推荐
- es6入门7--Set Map数据结构
本文作为ES6入门第十三章的学习整理笔记,可能会包含少部分个人的理解推测,若想阅读更详细的介绍,还请阅读原文ES6入门 一.set数据结构 1.set不接受重复值 ES6新增了Set构造函数用于创建s ...
- IT兄弟连 Java语法教程 流程控制语句 分支结构语句3
3 if-else if-else条件语句 if-else if-else的完整形式如下: if(判断条件A){ A语句块(判断条件A的值为true,执行) }else if(判断条件B){ B语句 ...
- Appium+java ---- Intellij IDEA +genymotion安装配置
引用文章:https://www.cnblogs.com/kaola8023/p/8442686.html Intellij IDEA 中配置Android SDK File-Project Stru ...
- MongoDB for OPS 03:分片 shard 集群
写在前面的话 上一节的复制集也就是主从能够解决我们高可用和数据安全性问题,但是无法解决我们的性能瓶颈问题.所以针对性能瓶颈,我们需要采用分布式架构,也就是分片集群,sharding cluster! ...
- Java8的Stream方法findAny空指针异常(NullPointerException)实例对比
实战介绍 学习完Java8的Stream方法,可能你正准备大展身手,却发现遇到不少问题,本篇文章为大家带来一个findAny方法抛出java.lang.NullPointerException的场景. ...
- Spring5源码解析2-register方法注册配置类
接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...
- go-百度贴吧-纵向爬取
百度贴吧纵向爬取 上一个是横向爬取的,这个纵向爬取,具体怎么做的看代码 package main import ( "fmt" "io" "net/h ...
- Qt Creator单步调试快捷键F10经常失灵问题
使用Qt Creator调试程序的时候经常会遇到F10单步调试快捷键不响应的问题. 打开调试菜单如下:有两个快捷键为F10的调试菜单项,于是快捷键冲突了! 解决办法:废话不说,直接上图 由于Start ...
- Gradle task简单使用
还望支持个人博客站:http://www.enjoytoday.cn task是什么 task是gradle构建脚本的最小运行单元,我们通过在gradle脚本中创建task任务,以期完成某个特定的功能 ...
- Linux中LVM逻辑卷管理
一.简介 LVM是逻辑盘卷管理(Logical Volume Manager)的简称,它是Linux环境下对磁盘分区 进行管理的一种机制,LVM是建立在硬盘和分区之上的一个逻辑层,来提高磁盘分区管理的 ...