Codeforces - 600E 树上启发式合并
题意:求每一个子树存在最多颜色的颜色代号和(可重复)
本题是离线统计操作,因此可以直接合并重儿子已达到\(O(nlogn)\)的复杂度
PS.不知道什么是启发式合并的可以这样感受一下:进行树链剖分,分出重儿子和轻儿子,每次离线dfs时保留重儿子得出的贡献,清除轻儿子的贡献并重新遍历
(反正是一种取代树上莫队的简单粗暴玩意,但是效率贼tm好)
唯一不解的小细节是似乎我在轻儿子的撤销操作中更新tmp存在问题,改了另一种写法就A了
想不出反例,求指教
Update:看出来了,是我傻缺..
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define erep(i,u) for(register int i=head[u];~i;i=nxt[i])
#define print(a) printf("%lld",(ll)(a))
#define println(a) printf("%lld\n",(ll)(a))
#define printbk(a) printf("%lld ",(ll)(a))
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot;
int CLOCK,size[MAXN],st[MAXN],ed[MAXN],pre[MAXN];
int cntVal[MAXN],cntNum[MAXN],tmp,n;
bool vis[MAXN];
ll sum[MAXN],ans[MAXN],c[MAXN];
void init(){
memset(head,-1,sizeof head);
memset(cntVal,0,sizeof cntVal);
memset(cntNum,0,sizeof cntNum);
memset(sum,0,sizeof sum);
memset(vis,0,sizeof vis);
tmp=0;tot=0;CLOCK=0;
}
void add(int u,int v){
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
swap(u,v);
to[tot]=v;nxt[tot]=head[u];head[u]=tot++;
}
void prepare(int u,int p){
size[u]=1;
st[u]=++CLOCK;pre[CLOCK]=u;
erep(i,u){
int v=to[i];
if(v==p)continue;
prepare(v,u);
size[u]+=size[v];
}
ed[u]=CLOCK;
}
void dfs(int u,int p,bool keep){
int mx=0,son=-1;
erep(i,u){
int v=to[i];
if(v==p)continue;
if(size[v]>mx){
mx=size[v];
son=v;
}
}
erep(i,u){
int v=to[i];
if(v==p)continue;
if(v==son) continue;
dfs(v,u,0);
}
if(~son) dfs(son,u,1);
erep(i,u){
int v=to[i];
if(v==p)continue;
if(v==son)continue;
rep(j,st[v],ed[v]){
int o=pre[j];
sum[cntVal[c[o]]]-=c[o];
cntNum[cntVal[c[o]]]--;
cntVal[c[o]]++;
cntNum[cntVal[c[o]]]++;
sum[cntVal[c[o]]]+=c[o];
if(tmp<cntVal[c[o]]) tmp=cntVal[c[o]];
}
}
sum[cntVal[c[u]]]-=c[u];
cntNum[cntVal[c[u]]]--;
cntVal[c[u]]++;
cntNum[cntVal[c[u]]]++;
sum[cntVal[c[u]]]+=c[u];
if(tmp<cntVal[c[u]]) tmp=cntVal[c[u]];
ans[u]=sum[tmp];
if(!keep){
rep(i,st[u],ed[u]){
int v=pre[i];
sum[cntVal[c[v]]]-=c[v];
cntNum[cntVal[c[v]]]--;
//if(tmp==cntVal[c[v]]&&cntNum[cntVal[c[v]]]==0) tmp--;
cntVal[c[v]]--;
cntNum[cntVal[c[v]]]++;
sum[cntVal[c[v]]]+=c[v];
if(cntNum[tmp]==0) tmp--;
}
}
}
int main(){
while(cin>>n){
init();
rep(i,1,n) c[i]=read();
rep(i,1,n) if(!vis[c[i]]){
sum[0]+=c[i];
cntNum[0]++;
vis[c[i]]=1;
}
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
}
prepare(1,-1);
dfs(1,-1,0);
rep(i,1,n){
if(i==n) println(ans[i]);
else printbk(ans[i]);
}
}
return 0;
}
Codeforces - 600E 树上启发式合并的更多相关文章
- Codeforces 600E - Lomsat gelral(树上启发式合并)
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对 ...
- Codeforces 208E - Blood Cousins(树上启发式合并)
208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ance ...
- 树上启发式合并(dsu on tree)学习笔记
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat ...
- 神奇的树上启发式合并 (dsu on tree)
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.ht ...
- CF EDU - E. Lomsat gelral 树上启发式合并
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最 ...
- dsu on tree (树上启发式合并) 详解
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...
- dsu on tree 树上启发式合并 学习笔记
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数) ...
- hdu6191(树上启发式合并)
hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到 ...
- csu1811(树上启发式合并)
csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \( ...
随机推荐
- CompositePattern(23种设计模式之一)
设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大 ...
- 529A And Yet Another Bracket Sequence
传送门 题目大意 给定有一个长度为n n的括号序列,现在有两种操作: 在任意一个位置插入有一个左括号或右括号 将末尾的一个括号放到最前面 可以对这个序列进行若干次操作,问在使括号序列合法的前提下,长度 ...
- CF519E A and B and Lecture Rooms
最近很颓……难题想不动……水题写不对,NOIP怕是
- Django框架 之 logging配置
Django框架 之 logging配置 logging配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 2 ...
- HttpClient connectionTimeout
转自:http://www.cnblogs.com/carlosk/archive/2013/03/12/2956502.html 前几天服务器端的产品经理跑来问我是否有做请求超时和响应超时的处理.我 ...
- Android内置和外置SD卡的位置获取
public class StorageUtils { private static String TAG="123"; // 获取主存储卡路径 内置内存卡路径 public st ...
- android canvas中rotate()和translate()两个方法详解
rotate()和translate() 1.看到这个题目的时候,有人会觉得这不就是一个对画布的旋转和平移的嘛,但是其中的细节的地方还是需要深究一下的. 例如:有个需求将TextView的文字竖直显示 ...
- http服务 WCF、Web API、Web service、WCF REST之间的区别
http服务 WCF.Web API.Web service.WCF REST之间的区别 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web ...
- Mybatis 延迟加载策略
延迟加载: 就是在需要用到数据时才进行加载,不需要用到数据时就不加载数据.延迟加载也称懒加载. 好处: 先从单表查询,需要时再从关联表去关联查询,大大提高数据库性能,因为查询单表要比关联查询多张表速 ...
- Educational Codeforces Round 61 (Rated for Div. 2) G(线段树,单调栈)
#include<bits/stdc++.h>using namespace std;int st[1000007];int top;int s[1000007],t[1000007];i ...