【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奔溃日志信息统计使用笔记
1.Bugly的集成很简单,直接一个pod就可以搞定 pod 'Bugly' 2.在官网上注册账号 3.初始化SDK 导入头文件 在工程的AppDelegate.m文件导入头文件 #import &l ...
- BAT批处理(五)
批处理程序 一.交互界面设计 没啥说的,看看设计的菜单界面吧:@echo offclstitle 终极多功能修复:menuclscolor 0Aecho.echo ================== ...
- 按Backspace键删除时,会出现^H
按Backspace键删除时,会出现^H 2014-08-12 19:38 1180人阅读 评论(0) 举报 版权声明:本文为博主原创文章,未经博主允许不得转载. 在linux/unix 平台的经常使 ...
- HashMap源码剖析及实现原理分析(学习笔记)
一.需求 最近开发中,总是需要使用HashMap,而为了更好的开发以及理解HashMap:因此特定重新去看HashMap的源码并写下学习笔记,以便以后查阅. 二.HashMap的学习理解 1.我们首先 ...
- MyBatis原理简介
1.什么是 MyBatis ? MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyB ...
- 【MVC】ASP.Net MVC 4项目升级MVC 5的方法
1.备份你的项目 2.从Web API升级到Web API 2,修改global.asax,将 ? 1 WebApiConfig.Register(GlobalConfiguration.Config ...
- Lucene笔记一
Lucene就是一个全文检索的工具,建立索引用的,类似于新华字典的目录 这里使用的是lucene-4.4.0版本,入门代码所需jar包如下图所示(解压lucene-4.4.0后的目录): 入门代码: ...
- [WC2005]双面棋盘
description 洛谷 给出一个\(n\times n\)的黑白棋盘. \(m\)次操作,每次将一个格子进行颜色翻转,求每次操作后的黑白四连通块数. data range \[n\le 200, ...
- 【BZOJ2648】SJY摆棋子(KD-Tree)
[BZOJ2648]SJY摆棋子(KD-Tree) 题面 BZOJ Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一 ...
- BZOJ3144:[HNOI2013]切糕——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3144 看着很像网络流,但是费用流貌似无法解决这个问题,其实甚至连忽略d的情况都做不到. 最小割? ...