【CodeForces】601 D. Acyclic Organic Compounds
【题目】D. Acyclic Organic Compounds
【题意】给定一棵带点权树,每个点有一个字符,定义一个结点的字符串数为往下延伸能得到的不重复字符串数,求min(点权+字符串数),n<=300000,time=3s。
【算法】trie合并||hash+线段树合并||dsu on tree
【题解】维护每个节点的Trie,那么每个节点的不重复字符串数是Trie的节点数。
每个节点Tire的根设为这个节点的字符(不是空字符)。
这样Trie的合并就很方便了,merge(a,b)表示将b并入a下一层,假设b的根字符为c:
如果存在trans(a,c),那么累计重叠一个节点,继续合并。
否则加入trans(a,c)=b,退出。
这样能统计出总共重叠多少个节点,merge结束后在size(a)中减去。
合并的复杂度分析和线段树合并分析相同,复杂度为$O(26*n)$。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=;
int n,tot,ans=,ansnum=,num[maxn],first[maxn],ch[maxn][],sz[maxn];
char s[maxn];
struct edge{int v,from;}e[maxn*];
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
int merge(int a,int b){
int x=s[b]-'a',sum;
if(ch[a][x]){
sum=;
for(int i=;i<;i++)if(ch[b][i])sum+=merge(ch[a][x],ch[b][i]);
}
else{
sum=;
ch[a][x]=b;
}
return sum;
}
void dfs(int x,int fa){
sz[x]=;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
dfs(e[i].v,x);
sz[x]+=sz[e[i].v];
sz[x]-=merge(x,e[i].v);
}
if(ans<num[x]+sz[x]){
ans=num[x]+sz[x];
ansnum=;
}else if(ans==num[x]+sz[x])ansnum++;
}
int main(){
n=read();
for(int i=;i<=n;i++)num[i]=read();
scanf("%s",s+);
for(int i=;i<n;i++){
int u=read(),v=read();
insert(u,v);insert(v,u);
}
dfs(,);
printf("%d\n%d",ans,ansnum);
return ;
}
hash+线段树合并:主要问题在于每次都会增加一个字符,取模后就破坏了原有顺序。
解决方法是,每个点记录从根到它的字符串的哈希值,两个遇到一起会消去的字符串一定从根开始就相同。
然后将这些哈希值离散化后线段树合并即可,复杂度O(n log n)。
平衡树+启发式合并,复杂度O(n log2n)。
注意:CodeForces卡自然溢出,可以取模1e18+7效果就和自然溢出差不多了。
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define ul unsigned long long
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
const int maxn=,base=;
int n,tot,cnt,first[maxn],root[maxn],num[maxn],ans=,ansnum=;
ul g[maxn],h[maxn],MOD=;
char s[maxn];
struct tree{int l,r,sum;}t[maxn*];
struct edge{int v,from;}e[maxn*];
void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
void dfs(int x,int fa,ul num){
g[x]=h[x]=(1ull*num*base+s[x]+)%MOD;
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
dfs(e[i].v,x,h[x]);
}
}
void build(int l,int r,int &k,int x){
if(!k)k=++cnt;t[k].sum=;
if(l==r)return;
int mid=(l+r)>>;
if(x<=mid)build(l,mid,t[k].l,x);
else build(mid+,r,t[k].r,x);
}
int merge(int l,int r,int a,int b){
if(!a||!b)return a^b;
if(l==r){t[a].sum=;return a;}
int mid=(l+r)>>;
t[a].l=merge(l,mid,t[a].l,t[b].l);
t[a].r=merge(mid+,r,t[a].r,t[b].r);
t[a].sum=t[t[a].l].sum+t[t[a].r].sum;
return a;
}
void ask(int x,int fa){
for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
ask(e[i].v,x);
root[x]=merge(,tot,root[x],root[e[i].v]);
}
if(num[x]+t[root[x]].sum>ans){
ans=num[x]+t[root[x]].sum;
ansnum=;
}
else if(num[x]+t[root[x]].sum==ans)ansnum++;
}
int main(){
n=read();
for(int i=;i<=n;i++)num[i]=read();
scanf("%s",s+);
for(int i=;i<n;i++){
int u=read(),v=read();
insert(u,v);insert(v,u);
}
dfs(,,);
sort(g+,g+n+);
tot=unique(g+,g+n+)-g-;
for(int i=;i<=n;i++)h[i]=lower_bound(g+,g+tot+,h[i])-g;
for(int i=;i<=n;i++)build(,tot,root[i],h[i]);
ask(,);
printf("%d\n%d",ans,ansnum);
return ;
}
dsu on tree:见官方题解。
【CodeForces】601 D. Acyclic Organic Compounds的更多相关文章
- Codeforces Round #333 (Div. 1) D. Acyclic Organic Compounds trie树合并
D. Acyclic Organic Compounds You are given a tree T with n vertices (numbered 1 through n) and a l ...
- 【CodeForces】915 D. Almost Acyclic Graph 拓扑排序找环
[题目]D. Almost Acyclic Graph [题意]给定n个点的有向图(无重边),问能否删除一条边使得全图无环.n<=500,m<=10^5. [算法]拓扑排序 [题解]找到一 ...
- 【Codeforces】Round #491 (Div. 2) 总结
[Codeforces]Round #491 (Div. 2) 总结 这次尴尬了,D题fst,E没有做出来.... 不过还好,rating只掉了30,总体来说比较不稳,下次加油 A:If at fir ...
- 【Codeforces】Round #488 (Div. 2) 总结
[Codeforces]Round #488 (Div. 2) 总结 比较僵硬的一场,还是手速不够,但是作为正式成为竞赛生的第一场比赛还是比较圆满的,起码没有FST,A掉ABCD,总排82,怒涨rat ...
- 【codeforces】【比赛题解】#937 CF Round #467 (Div. 2)
没有参加,但是之后几天打了哦,第三场AK的CF比赛. CF大扫荡计划正在稳步进行. [A]Olympiad 题意: 给\(n\)个人颁奖,要满足: 至少有一个人拿奖. 如果得分为\(x\)的有奖,那么 ...
- 【Codeforces】849D. Rooter's Song
[算法]模拟 [题意]http://codeforces.com/contest/849/problem/D 给定n个点从x轴或y轴的位置p时间t出发,相遇后按对方路径走,问每个数字撞到墙的位置.(还 ...
- 【CodeForces】983 E. NN country 树上倍增+二维数点
[题目]E. NN country [题意]给定n个点的树和m条链,q次询问一条链(a,b)最少被多少条给定的链覆盖.\(n,m,q \leq 2*10^5\). [算法]树上倍增+二维数点(树状数组 ...
- 【CodeForces】925 C.Big Secret 异或
[题目]C.Big Secret [题意]给定数组b,求重排列b数组使其前缀异或和数组a单调递增.\(n \leq 10^5,1 \leq b_i \leq 2^{60}\). [算法]异或 为了拆位 ...
- 【CodeForces】700 D. Huffman Coding on Segment 哈夫曼树+莫队+分块
[题目]D. Huffman Coding on Segment [题意]给定n个数字,m次询问区间[l,r]的数字的哈夫曼编码总长.1<=n,m,ai<=10^5. [算法]哈夫曼树+莫 ...
随机推荐
- iOS- 无处不在,详解iOS集成第三方登录(SSO授权登录<无需密码>)
1.前言 不多说,第三登录无处不在!必备技能,今天以新浪微博为例. 这是上次写的iOS第三方社交分享:http://www.cnblogs.com/qingche/p/3727559.html 可 ...
- 性能分析Linux服务器CPU利用率(转)
1. 指标范围 1.1 User mode CPU utilization+ System mode CPU utilization 合理值:60-85%,如果在一个多用户系统中us+sy时间超过 ...
- WEB安全测试要点总结
一.大类检查点: 二.测试项详细说明 上传功能 绕过文件上传检查功能 上传文件大小和次数限制 注册功能 注册请求是否安全传输 注册时密码复杂度是否后台校验 激活链接测试 重复注册 批量注册问题 登录 ...
- (转)linux IO 内核参数调优 之 参数调节和场景分析
1. pdflush刷新脏数据条件 (linux IO 内核参数调优 之 原理和参数介绍)上一章节讲述了IO内核调优介个重要参数参数. 总结可知cached中的脏数据满足如下几个条件中一个或者多个的时 ...
- 【EF】Entity Framework 6新特性:全局性地自定义Code First约定
应用场景 场景一:EF Code First默认使用类名作为表名,如果我们需要给表名加个前缀,例如将类名Category映射到表Shop_Category.将Product映射到Shop_Produc ...
- 【Python】python学习之总结
迭代器: def gen(): a = yield a a = a * yield a for i in gen(): print(i) 创建一个函数,循环体,yield循环到此就返回一个值.调用函数 ...
- linux系统过一两分钟就断开的时间更改
vi /etc/ssh/sshd_config LoginGraceTime 参考man sshd_config LoginGraceTime The server disconnects after ...
- poj 1018 Communication System (枚举)
Communication System Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22380 Accepted: ...
- vscode Variables Reference
vscode Variables Reference 您可以在以下链接中找到该列表:https://code.visualstudio.com/docs/editor/variables-refere ...
- [洛谷P4688][Ynoi2016]掉进兔子洞
题目大意:给定一个$n(n\leqslant10^5)$序列,$m(m\leqslant10^5)$个询问,每个询问给出$l_1,r_1,l_2,r_2,l_3,r_3$.令$s$为该三个区间的交集的 ...