ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【NOI2015】品酒大会【后缀数组】【并查集】

2019-08-06 18:36:19  阅读:285  来源: 互联网

标签:suffix int 查集 tp NOI2015 品酒 MAXN ans include


传送门

传送门

题意:给一个长度为NNN的字符串和一个长度为NNN的序列AAA,对于所有的k[0,N1]k \in [0,N-1]k∈[0,N−1],求选出两个数i,ji,ji,j满足lcp(suffix(i),suffix(j))=klcp(suffix(i),suffix(j))=klcp(suffix(i),suffix(j))=k的方案数和Ai×AjA_i \times A_jAi​×Aj​的最大值

数据范围:暴力跑不过

终于有个后缀自动机做不了的了

看到后缀的前缀,显然是后缀数组

显然求出heightheightheight数组,倒着排序

显然这是单调的

读到一个长度时,就把iii和i1i-1i−1合并并统计答案

显然可以用并查集

对于方案数,维护一个sizesizesize ,合并的时候相乘再计入答案

对于Ai×AjA_i \times A_jAi​×Aj​的最大值,维护当前AAA的最大值和次大值

然而有负数。根据意识流,再维护个最小值和次小值

瞎维护一通,信仰ACACAC

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 300005
using namespace std;
typedef long long ll;
const ll INF=1e18;
int sa[MAXN],rk[MAXN],tp[MAXN];
int c[MAXN],n,m='z';
int ht[MAXN];
char s[MAXN];
inline void Rsort()
{
	for (int i=1;i<=m;i++) c[i]=0;
	for (int i=1;i<=n;i++) ++c[rk[i]];
	for (int i=1;i<=m;i++) c[i]+=c[i-1];
	for (int i=n;i>=1;i--) sa[c[rk[tp[i]]]--]=tp[i];
}
void SA()
{
	for (int i=1;i<=n;i++) rk[i]=s[i],tp[i]=i;
	Rsort();
	for (int w=1,p=0;p<n;m=p,w<<=1)
	{
		p=0;
		for (int i=n-w+1;i<=n;i++) tp[++p]=i;
		for (int i=1;i<=n;i++) if (sa[i]>w) tp[++p]=sa[i]-w;
		Rsort();
		swap(rk,tp),rk[sa[1]]=p=1;
		for (int i=2;i<=n;i++)
			if (tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w]) rk[sa[i]]=p;
			else rk[sa[i]]=++p;
	}
	int p=0;
	for (int i=1;i<=n;i++)
	{
		if (p) --p;
		int j=sa[rk[i]-1];
		while (s[i+p]==s[j+p]) ++p;
		ht[rk[i]]=p;
	}
}
int a[MAXN],p[MAXN];
int fa[MAXN];
int find(const int& x){return fa[x]==x? x:fa[x]=find(fa[x]);}
ll mx[MAXN],sc[MAXN],mn[MAXN],cs[MAXN],siz[MAXN];
inline bool cmp(const int& a,const int& b){return ht[a]>ht[b];}
ll ans[MAXN][2],tmp[2];
int main()
{
	scanf("%d",&n);
	scanf("%s",s+1);
	SA();
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	for (int i=1;i<=n;i++) siz[i]=1,fa[i]=p[i]=i,mx[i]=mn[i]=a[sa[i]],sc[i]=-INF,cs[i]=INF;
	sort(p+1,p+n+1,cmp);
	int cur=n-1;
	tmp[1]=-INF;
	for (int i=1;i<=n;i++)
	{
		int x=find(p[i]),y=find(p[i]-1);
		tmp[0]+=siz[x]*siz[y];
		siz[x]+=siz[y];
		if (mx[y]>mx[x]) sc[x]=max(mx[x],sc[y]),mx[x]=mx[y];
		else if (mx[y]>sc[x]) sc[x]=mx[y];
		if (mn[y]<mn[x]) cs[x]=min(mn[x],cs[y]),mn[x]=mn[y];
		else if (mn[y]<cs[x]) cs[x]=mn[y];
		tmp[1]=max(tmp[1],max(mx[x]*sc[x],mn[x]*cs[x]));
		fa[y]=x;
		ans[ht[p[i]]][0]=tmp[0],ans[ht[p[i]]][1]=tmp[1];
	}
	for (int i=n-1;i>=0;i--) if (ans[i][0]==0&&ans[i][1]==-INF) ans[i][0]=ans[i+1][0],ans[i][1]=ans[i+1][1];
	for (int i=0;i<=n-1;i++) printf("%lld %lld\n",ans[i][0],ans[i][1]==-INF? 0:ans[i][1]);
	return 0;
}

标签:suffix,int,查集,tp,NOI2015,品酒,MAXN,ans,include
来源: https://blog.csdn.net/luositing/article/details/98643745

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有