UOJ131 [NOI2015] 品酒大会

考前挣扎(bu shi

之前留下来的坑

首先注意到 SAM的parent树 是反串的后缀树 也就是原串的前缀树

这个性质很重要 所以说我们在树上统计的时候两个点的lca就是两个后缀串的lcp 于是可以替代后缀数组(嘿嘿嘿

然后嘞我们树形dp 统计的size就是以这个串为前缀的子串个数

然后我们通过差分【最后后缀和 来进行统计对数

树形dp维护mn mx来进行查询最大 【有负所以要维护mn

这个最后还是要后缀max 但小心别把零转移过来

然后写写写 洛谷就过掉了

UOJ的hack数据真的吼2333

初始化的时候别忘了把0也清掉~

//Love and Freedom.
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define mxn 1200000
#define inf 2002122500
#define ll long long
using namespace std;

struct node
{
	int len,ch[26],fa,val,sz;
}t[mxn];
int lt,poi,rt;
struct edge{int to,lt;}e[mxn];
int in[mxn],cnt,a[mxn];
void add(int x,int y)
{
	e[++cnt].to=y; e[cnt].lt=in[x]; in[x]=cnt;
}
void insert(int c,int v)
{
	int p = lt, np = lt = ++poi; t[np].len = t[p].len+1; t[np].val = v; t[np].sz = 1;
	for(;p && !t[p].ch[c]; p = t[p].fa) t[p].ch[c] = np;
	if(!p){t[np].fa = rt; return;}
	int q = t[p].ch[c];
	if(t[q].len == t[p].len+1){t[np].fa = q;return;}
	int nq = ++poi; t[nq].len = t[p].len+1;
	memcpy(t[nq].ch,t[q].ch,sizeof(t[nq].ch));
	t[nq].fa = t[q].fa; t[q].fa = t[np].fa = nq;
	for(;p && t[p].ch[c] == q; p = t[p].fa)	t[p].ch[c] = nq;
}
void build()
{
	for(int i=2;i<=poi;i++)	add(t[i].fa,i);
}
int mx[mxn],mn[mxn],sz[mxn],val[mxn];ll ans1[mxn],ans2[mxn];
void dfs(int x)
{
	sz[x] = t[x].sz; val[x] = t[x].val;
	if(sz[x])	mx[x] = mn[x] = val[x];
	else	mx[x] = -inf,mn[x] = inf;
	for(int i=in[x];i;i=e[i].lt)
	{
		int y = e[i].to;
		dfs(y);
		if(mn[x]!=inf && mn[y]!=inf)
			ans1[t[x].len] = max(ans1[t[x].len],max((ll)mn[x]*mn[y],(ll)mx[x]*mx[y]));
		ans2[t[x].len] += (ll)sz[x]*sz[y];
		sz[x] += sz[y];
		mx[x] = max(mx[x],mx[y]);
		mn[x] = min(mn[x],mn[y]);
	}
}
char ch[mxn];
int main()
{
	int n;
	scanf("%d",&n);
	scanf("%s",ch+1);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	rt = lt = poi = 1;
	for(int i=n;i;i--)
		insert(ch[i]-'a',a[i]),ans1[i] = -(ll)inf*inf;
	ans1[0] = -(ll)inf*inf;
	build();
	dfs(rt);
	for(int i=n;~i;i--)
	{
		ans2[i] += ans2[i+1];
		if(ans2[i+1])
			ans1[i] = max(ans1[i],ans1[i+1]);
	}
	for(int i=0;i<n;i++)
	{
		if(!ans2[i])	printf("%d %d\n",0,0);
		else	printf("%lld %lld\n",ans2[i],ans1[i]);
	}
	return 0;
}

 

posted @ 2019-01-18 11:28  寒雨微凝  阅读(105)  评论(0编辑  收藏  举报