题目:

  P2664 树上游戏

分析:

  本来是练习点分治的时候看到了这道题。无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下。

  这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去,原树会被割成若干棵小树,那么这个颜色对每个点的贡献就是:树的大小n - 所在小树的大小sz。所以我们要求出对于每个点来说,删去所有这个点颜色的点,这个点以下的小树size,这个用一个dfs和一个类似前缀和相减的过程,就可以求出。

  接下来统计每个点的答案,就是所有颜色对这个点的贡献:n*颜色数-对于每种颜色这个点所处的小树size,这个用一遍dfs也可以求出来,类似容斥的思想。

  代码中有注释:

代码:

 #include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=;
struct node{int y,nxt;}e[N*];
ll n,sm,qwq,vis[N],ans[N],c=,h[N];
ll col[N],siz[N],tmp[N],lz[N],sn[N];
void add(int x,int y){
e[++c]=(node){y,h[x]};h[x]=c;
e[++c]=(node){x,h[y]};h[y]=c;
} void dfs(int x,int fa){
siz[x]=;ll cnt=tmp[col[fa]];
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa) dfs(y,x),siz[x]+=siz[y];
tmp[col[x]]++;if(fa){
lz[x]=siz[x]-tmp[col[fa]]+cnt;
tmp[col[fa]]+=lz[x];
} return ;
} void get(int x,int fa){
ll sgn=sn[col[fa]];
qwq+=lz[x]-sn[col[fa]];
sn[col[fa]]=lz[x];
ans[x]=n*sm-qwq+sn[col[x]];
for(int i=h[x],y;i;i=e[i].nxt)
if((y=e[i].y)!=fa) get(y,x);
sn[col[fa]]=sgn;
qwq-=lz[x]-sn[col[fa]];
} int main(){
scanf("%lld",&n);
for(int i=;i<=n;i++){
scanf("%lld",&col[i]);
if(!vis[col[i]])
vis[col[i]]=,sm++;
} for(int i=,x,y;i<n;i++)
scanf("%d%d",&x,&y),add(x,y);
dfs(,);
for(int i=;i<=;i++)
if(vis[i]) qwq+=n-tmp[i],
sn[i]=n-tmp[i];get(,);
for(int i=;i<=n;i++)
printf("%lld\n",ans[i]);return ;
}//lz[x]表示将x的父节点这种颜色的点全部删掉余下的这个
//小树的size
//sn记录的是对于每种颜色,当前深度以上的最近的小树sz
//qwq变量计算的是当前位置对于每种颜色所处的小树sz总和

dfs+树上统计

Luogu P2664 树上游戏 dfs+树上统计的更多相关文章

  1. Luogu P1278 单词游戏(dfs)

    P1278 单词游戏 题意 题目描述 \(Io\)和\(Ao\)在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何 ...

  2. 洛谷 P2664 树上游戏 解题报告

    P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...

  3. P2664 树上游戏

    P2664 树上游戏 https://www.luogu.org/problemnew/show/P2664 分析: 点分治. 首先关于答案的统计转化成计算每个颜色的贡献. 1.计算从根出发的路径的答 ...

  4. 【Luogu2664】树上游戏(点分治)

    [Luogu2664]树上游戏(点分治) 题面 洛谷 题解 很好的一道点分治题. 首先直接点分治,考虑过每个分治重心的链的贡献. 我们从分治重心开始找每种颜色,强制令一种颜色只在其到分治重心的链上第一 ...

  5. LG2664 树上游戏

    树上游戏 题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 $$sum_i=\sum_{j=1}^ns(i,j)$$ 现在他想让 ...

  6. Luogu P2680 运输计划(二分+树上差分)

    P2680 运输计划 题意 题目背景 公元\(2044\)年,人类进入了宇宙纪元. 题目描述 公元\(2044\)年,人类进入了宇宙纪元. \(L\)国有\(n\)个星球,还有\(n-1\)条双向航道 ...

  7. BZOJ_4238_电压_树上差分+dfs树

    BZOJ_4238_电压_树上差分+dfs树 Description 你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)” ...

  8. 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询

    题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...

  9. [luogu]P1070 道路游戏[DP]

    [luogu]P1070 道路游戏 题目描述小新正在玩一个简单的电脑游戏.游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针 ...

随机推荐

  1. c#file类读写

    private void button4_Click(object sender, EventArgs e) { FileStream fs = File.OpenRead(textBox1.Text ...

  2. TCP长链接调试利器nc

    最近做了不少TCP长链接的开发,包括服务端和客户端.本人感觉服务器端与客户端通信时最好采用字符串形式,这样可以做要平台无关,跨语言.如果采用对象序列化机制通用性会较差.另外采用字符串形式用nc调试很方 ...

  3. 普通平衡树与文艺平衡树的splay代码

    主要综合借鉴了yyb和马前卒两位大佬的. //普通平衡树 #include <cstdio> #include <cctype> #include <cstring> ...

  4. Codeforces 1131G(dp)

    传送门 与Codeforces1107G一起食用 思路 想到要用dp--然后常规地设dp[i]为推倒前i个牌的最小花费 有两种情况:一是当前这个推,二是不推而被别人推.对于第一种,需要找到这个左推(因 ...

  5. 调用submit()方式提交表单

    今天在看高级程序设计时看到的这样一段话: 在以调用submit()方法的形式提交表单时,不会触发submit事件 写了一个小例子做了下测试,的确如此: <form id="fm&quo ...

  6. jQuery prop() 与 removeProp()源码解读

    prop() prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't ...

  7. Ubuntu 18.10 使用VMware克隆后,克隆后的机器再手动更改interfaces配置文件后无法启动网络的解决办法

    克隆过程就略过了 配置interfaces root@client02:~# vim /etc/network/interfaces # interfaces() ) and ifdown() aut ...

  8. Ice-cream Tycoon9(线段树)

    线段树的一些基本应用,就是函数写了很多,有点繁琐. 以每个物品的单价建树,刚开始写了个裸的想水过去直接MLE了,然后又离散化了下. 离散化单价后建树,lz数组用来清零,s数组保存结点所含物品个数,co ...

  9. javascript ES 6 class 详解

    Introduction 上篇文章大致介绍了一些ES6的特性,以及如何在低版本浏览器中使用它们.本文是对class的详解. 译自Axel Rauschmayer的Classes in ECMAScri ...

  10. leetcode140 Word Break II

    思路: 直接爆搜会超时,需要使用记忆化搜索.使用map把已经计算过的情况记录下来,避免重复计算. 实现: class Solution { public: vector<string> w ...