Codeforces 601D. Acyclic Organic Compounds(四个愿望一次满足)

时间:2023-03-10 07:02:10
Codeforces 601D. Acyclic Organic Compounds(四个愿望一次满足)

  trie合并的裸题...因为最多只有n个点,所以最多合并n次,复杂度$O(N*26)$。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
using namespace std;
const int maxn=, inf=1e9;
struct poi{int too, pre;}e[maxn<<];
struct tjm{int nxt[], size;}tree[maxn];
int n, x, y, ans, cnt, tot;
int last[maxn], c[maxn];
char s[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void merge(int &x, int y)
{
if(!x || !y) {x+=y; return;}
tree[x].size=;
for(int i=;i<;i++)
merge(tree[x].nxt[i], tree[y].nxt[i]), tree[x].size+=tree[tree[x].nxt[i]].size;
}
void dfs(int x, int fa)
{
tree[x].size=;
for(int i=last[x], too;i;i=e[i].pre)
if((too=e[i].too)!=fa)
{
dfs(too, x); int tmp=tree[tree[x].nxt[s[e[i].too]-'a']].size;
merge(tree[x].nxt[s[e[i].too]-'a'], e[i].too);
tree[x].size+=tree[tree[x].nxt[s[e[i].too]-'a']].size-tmp;
}
if(tree[x].size+c[x]>ans) ans=tree[x].size+c[x], cnt=;
else if(tree[x].size+c[x]==ans) cnt++;
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(c[i]); scanf("%s", s+);
for(int i=;i<n;i++) read(x), read(y), add(x, y), add(y, x);
dfs(, ); printf("%d\n%d", ans, cnt);
}

  当然还可以直接上哈希+平衡树+启发式合并,用set自带去重就好了,复杂度$O(Nlog^2N)$。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<set>
#define ll long long
using namespace std;
const int maxn=, inf=1e9;
const ll mod=;
typedef set<ll>::iterator ddq;
struct poi{int too, pre;}e[maxn<<];
int n, x, y, tot, ans, ansnum;
int last[maxn], c[maxn], root[maxn];
ll hs[maxn];
char ch[maxn];
set<ll>s[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
inline int merge(int x, int y)
{
if(s[x].size()<s[y].size()) swap(x, y);
for(ddq ity=s[y].begin();ity!=s[y].end();ity++) s[x].insert(*ity);
s[y].clear(); return x;
}
void dfs(int x, int fa)
{
hs[x]=(hs[fa]*+ch[x]-'a'+)%mod;
s[x].insert(hs[x]); root[x]=x;
for(int i=last[x], too;i;i=e[i].pre)
if((too=e[i].too)!=fa)
{
dfs(too, x);
root[x]=merge(root[x], root[too]);
}
int size=s[root[x]].size();
if(size+c[x]>ans) ans=size+c[x], ansnum=;
else if(size+c[x]==ans) ansnum++;
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(c[i]);
scanf("%s", ch+);
for(int i=;i<n;i++) read(x), read(y), add(x, y), add(y, x);
dfs(, ); printf("%d\n%d", ans, ansnum);
}

  当然还可以hash之后用dsu on tree,复杂度$O(NlogN)$。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=, inf=1e9;
const ll mod=;
struct poi{int too, pre;}e[maxn<<];
int n, x, y, N, tot, sum, skip, ANS, ANSNUM;
int c[maxn], last[maxn], son[maxn], size[maxn], cnt[maxn], ans[maxn];
ll b[maxn], hs[maxn];
char s[maxn];
inline void read(int &k)
{
int f=; k=; char c=getchar();
while(c<'' || c>'') c=='-' && (f=-), c=getchar();
while(c<='' && c>='') k=k*+c-'', c=getchar();
k*=f;
}
inline void add(int x, int y){e[++tot]=(poi){y, last[x]}; last[x]=tot;}
void dfs1(int x, int fa)
{
size[x]=; b[x]=hs[x]=(hs[fa]*+s[x]-'a'+)%mod;
for(int i=last[x], too;i;i=e[i].pre)
if((too=e[i].too)!=fa)
{
dfs1(too, x);
size[x]+=size[too];
if(size[too]>size[son[x]]) son[x]=too;
}
}
void update(int x, int fa, int delta)
{
if(delta==) sum+=(!cnt[hs[x]]);
cnt[hs[x]]+=delta;
for(int i=last[x], too;i;i=e[i].pre)
if((too=e[i].too)!=fa && too!=skip) update(too, x, delta);
}
void dfs2(int x, int fa, bool heavy)
{
for(int i=last[x], too;i;i=e[i].pre)
if((too=e[i].too)!=fa && too!=son[x]) dfs2(too, x, );
if(son[x]) dfs2(son[x], x, ), skip=son[x];
update(x, fa, ); ans[x]=sum; skip=;
if(!heavy) update(x, fa, -), sum=;
if(ans[x]+c[x]>ANS) ANS=ans[x]+c[x], ANSNUM=;
else if(ans[x]+c[x]==ANS) ANSNUM++;
}
int main()
{
read(n);
for(int i=;i<=n;i++) read(c[i]);
scanf("%s", s+);
for(int i=;i<n;i++) read(x), read(y), add(x, y), add(y, x);
dfs1(, );
N=n; sort(b+, b++N); N=unique(b+, b++N)-b-;
for(int i=;i<=n;i++) hs[i]=lower_bound(b+, b++N, hs[i])-b;
dfs2(, , ); printf("%d\n%d", ANS, ANSNUM);
}

  还可以hash之后写线段树合并,复杂度$O(NlogN)$。(真的懒得写了T T