传送门

题意:给一个串,每个位置有一个权值,当S[s...s+len−1]=S[t...t+len−1]&&S[s...s+len]̸=S[t..t+len]S[s...s+len-1]=S[t...t+len-1]\&\&S[s...s+len]\not=S[t..t+len]S[s...s+len−1]=S[t...t+len−1]&&S[s...s+len]̸​=S[t..t+len]时我们称两个字串是"lenlenlen“相似的,而这对字串的价值等于as∗ata_s*a_tas​∗at​,现在问对于i=0→n−1i=0\rightarrow n-1i=0→n−1,有多少对”iii"相似字串,以及这几对串的价值的最大值是多少。


思路:

我们把samsamsam建出来,然后在后缀链接树上面树形dpdpdp出子树的size,max,second_mx,min,second_minsize,max,second\_mx,min,second\_minsize,max,second_mx,min,second_min来更新长度在[lenfa+1,lenp][len_{fa}+1,len_p][lenfa​+1,lenp​]之间的答案。

这个可以用线段树维护。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	bool f=1;
	char ch=getchar();
	while(!isdigit(ch))f^=ch=='-',ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return f?ans:-ans;
}
const int N=3e5+5,M=6e5+5;
typedef long long ll;
const ll inf=1e18;
int n,m,a[N];
namespace SGT{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	ll sum[N<<2],mx[N<<2];
	inline void build(int p,int l,int r){
		sum[p]=0,mx[p]=-inf;
		if(l==r)return;
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void updsum(int p,int l,int r,int ql,int qr,ll v){
		if(ql<=l&&r<=qr){sum[p]+=v;return;}
		if(qr<=mid)updsum(lc,l,mid,ql,qr,v);
		else if(ql>mid)updsum(rc,mid+1,r,ql,qr,v);
		else updsum(lc,l,mid,ql,qr,v),updsum(rc,mid+1,r,ql,qr,v);
	}
	inline void updmax(int p,int l,int r,int ql,int qr,ll v){
		if(ql<=l&&r<=qr){mx[p]=max(mx[p],v);return;}
		if(qr<=mid)updmax(lc,l,mid,ql,qr,v);
		else if(ql>mid)updmax(rc,mid+1,r,ql,qr,v);
		else updmax(lc,l,mid,ql,qr,v),updmax(rc,mid+1,r,ql,qr,v);
	}
	inline void query(int p,int l,int r,ll v1,ll v2){
		v1+=sum[p],v2=max(v2,mx[p]);
		if(l==r){if(l^n)cout<<v1<<' '<<(v2+inf?v2:0)<<'\n';return;}
		query(lc,l,mid,v1,v2),query(rc,mid+1,r,v1,v2);
	}
	#undef lc
	#undef rc
	#undef mid
}
namespace sam{
	int son[M][26],len[M],link[M],siz[M],last=1,tot=1;
	ll mx[M],smx[M],mn[M],smn[M],sum[M];
	inline void init(){
		memset(siz,0,sizeof(siz));
		memset(mx,-0x7f,sizeof(mx)),memset(smx,-0x7f,sizeof(smx));
		memset(mn,0x7f,sizeof(mx)),memset(smn,0x7f,sizeof(smn));
	}
	inline void insert(const int&x,const int&id){
		int p=last,np=++tot;
		siz[np]=1,len[last=np]=len[p]+1;
		mx[np]=mn[np]=a[id];
		while(p&&!son[p][x])son[p][x]=np,p=link[p];
		if(!p){link[np]=1;return;}
		int q=son[p][x],nq;
		if(len[q]==len[p]+1){link[np]=q;return;}
		len[nq=++tot]=len[p]+1,link[nq]=link[q],link[q]=link[np]=nq;
		memcpy(son[nq],son[q],sizeof(son[q]));
		while(p&&son[p][x]==q)son[p][x]=nq,p=link[p];
	}
	inline void pre(){
		static int rk[N<<1],cnt[N<<1];
		for(ri i=1;i<=tot;++i)++cnt[len[i]];
		for(ri i=1;i<=tot;++i)cnt[i]+=cnt[i-1];
		for(ri i=tot;i;--i)rk[cnt[len[i]]--]=i;
		SGT::build(1,1,n);
		for(ri i=tot,p,fa;i^1;--i){
			p=rk[i],fa=link[p];
			siz[fa]+=siz[p];
			if(smx[p]>mx[fa])smx[fa]=mx[fa],mx[fa]=smx[p];
			else smx[fa]=max(smx[fa],smx[p]);
			if(mx[p]>mx[fa])smx[fa]=mx[fa],mx[fa]=mx[p];
			else smx[fa]=max(smx[fa],mx[p]);
			if(smn[p]<mn[fa])smn[fa]=mn[fa],mn[fa]=smn[p];
			else smn[fa]=min(smn[fa],smn[p]);
			if(mn[p]<mn[fa])smn[fa]=mn[fa],mn[fa]=mn[p];
			else smn[fa]=min(smn[fa],mn[p]);
			SGT::updsum(1,1,n,len[fa]+1,len[p],(ll)siz[p]*(siz[p]-1)/2);
			SGT::updmax(1,1,n,len[fa]+1,len[p],max((mx[p]-mx[0]&&smx[p]-smx[0])?mx[p]*smx[p]:-inf,(mn[p]-mn[0]&&smn[p]-smn[0])?mn[p]*smn[p]:-inf));
		}
	}
}
char s[N];
int main(){
	n=read();
	scanf("%s",s+1),reverse(s+1,s+n+1);
	for(ri i=1;i<=n;++i)a[i]=read();
	reverse(a+1,a+n+1),sam::init();
	for(ri i=1;i<=n;++i)sam::insert(s[i]-'a',i);
	sam::pre(),sort(a+1,a+n+1);
	cout<<(ll)n*(n-1)/2<<' '<<max((ll)a[1]*a[2],(ll)a[n]*a[n-1])<<'\n';
	SGT::query(1,1,n,0,-inf);
	return 0;
}

2019.02.28 bzoj4199: [Noi2015]品酒大会(sam+线段树)的更多相关文章

  1. BZOJ4199 NOI2015品酒大会(后缀树)

    利用SAM建出后缀树,树上每个节点计算一下|right|.right集合中ai的最大.次大.最小.次小值即可. #include<iostream> #include<cstdio& ...

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

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

  3. [UOJ#131][BZOJ4199][NOI2015]品酒大会

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

  4. [bzoj4199][Noi2015]品酒大会_后缀自动机_后缀树_树形dp

    品酒大会 bzoj-4199 Noi-2015 题目大意:给定一个字符串,如果其两个子串的前$r$个字符相等,那么称这两个子串的开头两个位置$r$相似.如果两个位置勾兑在一起那么美味度为两个位置的乘积 ...

  5. [BZOJ4199][NOI2015]品酒大会

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

  6. bzoj4199: [Noi2015]品酒大会(后缀数组)

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

  7. BZOJ4199 [Noi2015]品酒大会 【后缀数组 + 单调栈 + ST表】

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

  8. [BZOJ4199][Noi2015]品酒大会 树形DP+后缀自动机

    由于要找后缀的前缀,所以先用反串建立SAM. link边组成了后缀树. 两个子串的最长公共前缀是LCA的step 树形dp即可. #include<iostream> #include&l ...

  9. 并不对劲的bzoj4199: [Noi2015]品酒大会

    传送门-> 又称普及大会. 这题没什么好说的……后缀自动机裸题……并不对劲的人太菜了,之前照着标程逐行比对才过了这道题,前几天刚刚把这题一遍写对…… 这题的输出和某两点相同后缀的长度有关,那么把 ...

随机推荐

  1. web--webstorm的一些常用快捷键

    Webstorm的一些常用快捷键   下面是Webstorm的一些常用快捷键: Alt+回车 导入包,自动修正 1. ctrl + shift + n: 打开工程中的文件,目的是打开当前工程下任意目录 ...

  2. js基础系列之【原型和原型链】

    声明:形成本文的出发点仅仅是个人总结记录,避免遗忘,并非详实的教程:文中引用了经过个人加工的其它作者的内容,并非原创.学海无涯 引入问题 一般我们是这样写的: (需求驱动技术,疑问驱动进步) // 构 ...

  3. Linux下安装jdk8步骤详述

    作为Java开发人员,在Linux下安装一些开发工具是必备技能,本文以安装jdk为例,详细记录了每一步的操作命令,以供参考. 0.下载jdk8 登录网址:http://www.oracle.com/t ...

  4. 爬虫:输入网页之后爬取当前页面的图片和背景图片,最后打包成exe

    环境:py3.6 核心库:selenium(考虑到通用性,js加载的网页).pyinstaller 颜色显示:colors.py colors.py  用于在命令行输出文字时,带有颜色,可有可无. # ...

  5. pycharm 调试django项目时,debug断点没反应???

    入门python.django框架时,使用pycharm断点调试时,发现打的断点没反应,不起作用!上网上稍微一查,90%的都差不多,需要新建一个python程序,重新配置一遍,的确可以成功! 操作链接 ...

  6. leetCode21: 合并两个有序列表

    将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1->2- ...

  7. 在线安装TIDB集群

     在线安装TiDB集群 服务器准备 说明:TiDB8需要能够连接外网,以便下载各类安装包 TiDB4非必须,但最好是有一台,因为后续测试Mysql数据同步或者进行性能比较时,都要用到 TiKV最好是采 ...

  8. git 第一次提交代码

    git init git add README.md git commit -m "first commit" git remote add origin https://git. ...

  9. 【395】yield 和 yield from

    yield:生成器 yield from:将生成器 yield 的内容相当于逐一在 yield 一般 参考:Python 3: Using "yield from" in Gene ...

  10. e1000

    http://blog.csdn.net/sdulibh/article/details/41826221 http://blog.csdn.net/evenness/article/details/ ...