[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]品酒大会的更多相关文章

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

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

  2. [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机

    [LOJ 2134][UOJ 132][BZOJ 4200][NOI 2015]小园丁与老司机 题意 给定平面上的 \(n\) 个整点 \((x_i,y_i)\), 一共有两个问题. 第一个问题是从原 ...

  3. [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程

    [LOJ 2718][UOJ 393][BZOJ 5415][NOI 2018]归程 题意 给定一张无向图, 每条边有一个距离和一个高度. 再给定 \(q\) 组可能在线的询问, 每组询问给定一个点 ...

  4. [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分

    [LOJ 2083][UOJ 219][BZOJ 4650][NOI 2016]优秀的拆分 题意 给定一个字符串 \(S\), 求有多少种将 \(S\) 的子串拆分为形如 AABB 的拆分方案 \(| ...

  5. [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士

    [LOJ 2721][UOJ 396][BZOJ 5418][NOI 2018]屠龙勇士 题意 题面好啰嗦啊直接粘LOJ题面好了 小 D 最近在网上发现了一款小游戏.游戏的规则如下: 游戏的目标是按照 ...

  6. UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)

    水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.org/problemnew/show/P2178 https://www.lydsy.com/JudgeOnline ...

  7. 【UOJ #131】【NOI 2015】品酒大会

    http://uoj.ac/problem/131 求出后缀数组和height数组后,从大到小扫相似度进行合并,每次相当于合并两个紧挨着的区间. 合并区间可以用并查集来实现,每个区间的信息都记录在这个 ...

  8. uoj 131/bzoj 4199 [NOI2015]品酒大会 后缀树+树d

    题目大意 见uoj131 分析 题目的提示还是很明显的 \(r\)相似就就代表了\(0...r-1\)相似 建出后缀树我们能dfs算出答案 再后缀和更新一下即可 注意 细节挺多的,但数据很良心 不然我 ...

  9. [NOI 2015]品酒大会

    Description 题库链接 \(n\) 杯鸡尾酒排成一行,其中第 \(i\) 杯酒 (\(1 \leq i \leq n\)) 被贴上了一个标签 \(s_i\),每个标签都是 \(26\) 个小 ...

随机推荐

  1. 用CSS绘制实体三角形

    用CSS绘制实体三角形 使用CSS盒模型中的border(边框)即可实现如下所示的三角形: .box { width: 0; height: 0; border-width: 100px; borde ...

  2. 微信小程序开发练习

    微信小程序开发工具git管理 https://blog.csdn.net/qq_36672905/article/details/82887102 这个开发工具的界面和交互真的是熟悉又友好,吹爆他

  3. C++教程详解

    第一篇:基础篇 简介.环境配置.基本语法.注释.数据类型.变量类型.变量作用域.常量.修饰符类型. 存储类.运算符.循环.判断.函数.数字.数组.字符串.指针.引用.日期&时间. 基本的输入输 ...

  4. C#位运算实际作用之操作整型某一位

    1.前言 前几天写了两篇关于c#位运算的文章 c#位运算基本概念与计算过程 C#位运算实际运用 在文中也提到了位运算的实际作用之一就是合并整型,当时引用了一个问题: C# 用两个short,一个int ...

  5. python集合、元组、字典

    主要内容: 2.集合 3.元组 4.字典 复习: 字符串和元组一样,只能读不能写.列表和字典可以嵌套任何东西,列表可以嵌套列表 L = list("hello")  # L = [ ...

  6. 暑期班--JAVA无敌课程---第一天-Day01-----Java基础

    1.Java发展历史 1.1Games Golsing Java创始人 2.What is JDK 3.记本本开发第一个Java程序 巴拉巴拉 巴拉巴拉 巴拉巴拉 巴拉巴拉 巴拉巴拉 巴拉巴拉 巴拉巴 ...

  7. 新安装ubuntu系统的简单优化

    新安装的ubuntu系统,需要做下简单的优化,使其符合常用习惯,优化过程的命令与centos大都不一致,撰文备份,以备所需: 1.获取ubuntu系统root权限 在终端输入sudo passwd r ...

  8. Numpy数值类型与数值运算-03

    什么是NumPy? NumPy是Python中科学计算的基本软件包.它是一个Python库,提供多维数组对象,各种派生对象(例如蒙版数组和矩阵) 以及各种例程,用于对数组进行快速操作,包括数学,逻辑, ...

  9. Octave Convolution详解

    前言 Octave Convolution来自于这篇论文<Drop an Octave: Reducing Spatial Redundancy in Convolutional Neural ...

  10. centos 8 docker-ce 安装

    https://www.techrepublic.com/article/a-better-way-to-install-docker-on-centos-8/ https://linuxconfig ...