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

时间:2021-12-06 03:58:41

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

题面

洛谷

题解

很好的一道点分治题。

首先直接点分治,考虑过每个分治重心的链的贡献。

我们从分治重心开始找每种颜色,强制令一种颜色只在其到分治重心的链上第一次出现的位置统计贡献,假设子树大小是\(size\),那么对于当前分治重心的其他所有子树都会产生\(size\)的贡献。

那么考虑当前分治重心每个子树的每个点会得到的贡献,首先把这棵子树内的贡献删去,然后记录其他所有颜色的贡献和。如果当前颜色在这棵子树内第一次出现,那么其他所有子树都必定会产生贡献,那么把这部分贡献加上,继续递归就行了。

详细的看看代码吧。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define pb push_back
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
vector<int> E[MAX];
int n,c[MAX];ll ans[MAX];
int mx,Size,rt,sz[MAX];
bool vis[MAX];
void Getroot(int u,int ff)
{
sz[u]=1;int ret=0;
for(int v:E[u])
{
if(v==ff||vis[v])continue;
Getroot(v,u);sz[u]+=sz[v];
ret=max(ret,sz[v]);
}
ret=max(ret,Size-sz[u]);
if(ret<mx)mx=ret,rt=u;
}
int cnt[MAX];ll num[MAX],sum;
void dfs(int u,int ff,int opt)
{
if(!cnt[c[u]]++)num[c[u]]+=opt*sz[u],sum+=opt*sz[u];
for(int v:E[u])if(v!=ff&&!vis[v])dfs(v,u,opt);
--cnt[c[u]];
}
void dfs(int u,int ff)
{
if(!cnt[c[u]]++)sum+=Size-num[c[u]];
ans[u]+=sum;
for(int v:E[u])if(v!=ff&&!vis[v])dfs(v,u);
if(!--cnt[c[u]])sum-=Size-num[c[u]];
}
void Divide(int u)
{
vis[u]=true;Getroot(u,0);
dfs(u,0,1);ans[u]+=sum;Size=sz[u];
for(int v:E[u])
{
if(vis[v])continue;
num[c[u]]-=sz[v];sum-=sz[v];Size-=sz[v];
cnt[c[u]]=1;dfs(v,u,-1);cnt[c[u]]=0;
dfs(v,u);
cnt[c[u]]=1;dfs(v,u,1);cnt[c[u]]=0;
num[c[u]]+=sz[v];sum+=sz[v];Size+=sz[v];
}
dfs(u,0,-1);
for(int v:E[u])
{
if(vis[v])continue;
mx=Size=sz[v];Getroot(v,u);
Divide(rt);
}
}
int main()
{
n=read();
for(int i=1;i<=n;++i)c[i]=read();
for(int i=1,u,v;i<n;++i)u=read(),v=read(),E[u].pb(v),E[v].pb(u);
mx=Size=n;Getroot(1,0);
Divide(rt);
for(int i=1;i<=n;++i)printf("%lld\n",ans[i]);
return 0;

【Luogu2664】树上游戏(点分治)的更多相关文章

  1. 洛谷P2664 树上游戏&lpar;点分治&rpar;

    题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...

  2. 洛谷P2664 树上游戏——点分治

    原题链接 被点分治虐的心态爆炸了 题解 发现直接统计路径上的颜色数量很难,考虑转化一下统计方式.对于某一种颜色\(c\),它对一个点的贡献为从这个点出发且包含这种颜色的路径条数. 于是我们先点分一下, ...

  3. &lbrack;Luogu2664&rsqb;树上游戏

    题面戳我 sol 点分.我们面临的最主要一个问题,就是如何在\(O(n)\)的时间内算出所有LCA为根的点对的贡献,还要分别累加到它们自己的答案中去. \(num_i\):每一种颜色的数量.你可以认为 ...

  4. 【洛谷P2664】 树上游戏 点分治

    code: #include <bits/stdc++.h> #define N 200009 #define ll long long #define setIO(s) freopen( ...

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

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

  6. P2664 树上游戏

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

  7. Luogu P2664 树上游戏 dfs&plus;树上统计

    题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...

  8. LG2664 树上游戏

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

  9. poj1741 树上的点分治

    题意: 一棵10000个点的树,每条边的长不超过1000,给定一个值k,问距离不超过k的点对数有多少.(多组数据) 输入样例: 5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0输出样例: ...

随机推荐

  1. mysql 关联查询的执行顺序

    STRAIGHT JOIN : 能强制按照顺序关联表(应该是)

  2. jQuery EasyUI 使用笔记

    大家有四次抢票机会.第一次是放票时间之后的30分钟.第二次机会是开车前的15天.第三个机会是开车前的48小时.第四个机会是开车前的24小时. $("#gys_key").combo ...

  3. JSBinding&plus;Bridge&period;Net:框架代码与逻辑代码的关系

    在JSB+Bridge工程中你可以同时维护Cs版本和Js版本的游戏. 框架代码:简称framework,表示那些不进行热更的代码.注意,这包括你自己写的代码,也包括引用的Dll,比如UnityEngi ...

  4. Android基于mAppWidget实现手绘地图(十三)–如何显示&sol;隐藏任意类型的地图对象

    这个很简单,想要显示或隐藏任意类型的地图对象,首先要对地图对象进行分类.不同类型的地图对象放置到不同的地图图层上,然后控制地图图层的显示/隐藏即可. 实例: Layer sportsLayer = m ...

  5. Android&lowbar;Nexus4&lowbar;屏幕截图

    1. 一般都是 音量-键 + 电源键,同时按一秒以上 2. 3.

  6. PHP取二进制文件头快速判断文件类型的实现代码

    通过读取文件头信息来识别文件的真实类型. 一般我们都是按照文件扩展名来判断文件类型,但是这个很不靠谱,轻易就通过修改扩展名来躲避了,一般必须要读取文件信息来识别,PHP扩展中提供了类似 exif_im ...

  7. 如何提取出ppt中的文字?

    最近在看一位老师的教学视频,视频里大部分的知识都记录在ppt里,于是很想将ppt中的文字提取出来,如果我一页一页地粘贴复制的话,效率低到吓人,因为一章的ppt有130多页,于是在网上搜索了一下方法,与 ...

  8. C&num;编辑基础笔记

    目录 1.     .NET .NET Framework是一种多语言的平台,一种技术. 而c#是基于其上面的一种语言.    1 2.     Winform 桌面应用程序[从.net平台上面开发的 ...

  9. &lbrack;elk&rsqb;验证mapping字段数和数据字段数关系

    验证一个mapping下字段缺少或者超过 结论: 没有什么不可以. 1.如果数据字段不在mapping里,则动态会更新mapping. 2.数据字段数也可以小于mapping里字段数 创建一个mapp ...

  10. 【整理】Java 11新特性总结

    闲语 2018年9月25日,Java 11正式发布,与JDK 10不同,JDK 11将提供长期支持,还将作为Java平台的参考实现以及标准版(Java SE)11.Oracle直到2023年9月都会为 ...