[LuoGu]P2664 树上游戏
这题真的好.
看到树上路径, 脑子里就要点分治
这一题对于每个点都要计算一遍, 如果暴算实在不好算, 这样我们就可以考虑算贡献.
直接计算每种颜色的贡献.
因为一条过重心的路径中, 可能两边都会有相同颜色, 那么我们就只考虑当前点到分治中心的链上.
然后把多算的这条链上的东西删除就可以了.
Copy From Here
那么我们就可以这样做了:
1.对树进行第一遍dfs,预处理size和上方性质中的贡献。(开一个color数组即可记录贡献),同时记录贡献总和sum
2.枚举跟的所有子树,先把子树扫一遍清除其在color数组中的所有贡献。接着,对于该子树中的每一个点j:
设X=sigma color[j 到根上(不包括根)的所有颜色] 由于这些颜色已经出现过,我们不能在该子树外计算其贡献)
设num为j到根上(不包括根)的颜色数
设Y为size[root]-size[该子树](即所有其他子树+根的点数)
则ans[j]+=sum-X+num*Y;
3.别忘了计算单独root的ans
ans[root]+=sum-color[根的颜色]+size[root]
4.清空贡献数组以及其他东西
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)
#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)
#define clar(a, b) memset((a), (b), sizeof(a))
#define debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
int read() {
char ch = getchar();
int x = 0, flag = 1;
for (;!isdigit(ch); ch = getchar()) if (ch == '-') flag *= -1;
for (;isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
return x * flag;
}
void write(int x) {
if (x < 0) putchar('-'), x = -x;
if (x >= 10) write(x / 10);
putchar(x % 10 + 48);
}
const int Maxn = 100009;
struct edge {
int to, nxt;
}g[Maxn << 1];
int n, a[Maxn], head[Maxn], e;
void add(int u, int v) {
g[++e] = (edge){v, head[u]}, head[u] = e;
}
void init() {
clar(head, -1);
n = read();
rep (i, 1, n) a[i] = read();
rep (i, 1, n - 1) {
int u = read(), v = read();
add(u, v), add(v, u);
}
}
LL ans[Maxn], vis[Maxn], Tmp, heart;
int size[Maxn];
void dfs(int u, int pa) {
size[u] = 1;
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa && !vis[v]) {
dfs(v, u);
size[u] += size[v];
}
}
}
void centroid(int u, int pa, int field) {
int bbs = field - size[u];
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (!vis[v] && v != pa) {
centroid(v, u, field);
bbs = max(bbs, size[v]);
}
}
if (bbs < Tmp) Tmp = bbs, heart = u;
}
LL color[Maxn], Sum, cnt[Maxn], size1[Maxn];
void dfs_init(int u, int pa) {
size1[u] = 1; ++cnt[a[u]];
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa && !vis[v]) {
dfs_init(v, u);
size1[u] += size1[v];
}
}
if (cnt[a[u]] == 1) {
color[a[u]] += size1[u];
Sum += size1[u];
}
--cnt[a[u]];
}
void change(int u, int pa, int delta) {
++cnt[a[u]];
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa && !vis[v]) change(v, u, delta);
}
if (cnt[a[u]] == 1) {
color[a[u]] += size1[u] * 1ll * delta;
Sum += size1[u] * 1ll * delta;
}
--cnt[a[u]];
}
void count(int u, int pa, int X, int Y, int num) {
++cnt[a[u]];
if (cnt[a[u]] == 1) {
X += color[a[u]];
++Y;
}
ans[u] += Sum - X + num * Y;
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (!vis[v] && v != pa) count(v, u, X, Y, num);
}
--cnt[a[u]];
}
void dfs_clear(int u, int pa) {
color[a[u]] = 0, cnt[a[u]] = 0, size1[u] = 0;
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (v != pa && !vis[v]) dfs_clear(v, u);
}
}
void calc(int u) {
dfs_init(u, 0);
ans[u] += Sum - color[a[u]] + size1[u];
for (int i = head[u]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (!vis[v]) {
++cnt[a[u]];
Sum -= size1[v]; color[a[u]] -= size1[v];
change(v, u, -1);
--cnt[a[u]];
count(v, u, 0, 0, size1[u] - size1[v]);
++cnt[a[u]];
Sum += size1[v]; color[a[u]] += size1[v];
change(v, u, 1);
--cnt[a[u]];
}
}
dfs_clear(u, 0), Sum = 0;
}
void divConquer(int u) {
dfs(u, 0), Tmp = INT_MAX;
centroid(u, 0, size[u]);
calc(heart); vis[heart] = 1;
for (int i = head[heart]; ~i; i = g[i].nxt) {
int v = g[i].to;
if (!vis[v]) divConquer(v);
}
}
void solve() {
divConquer(1);
rep (i, 1, n) printf("%lld\n", ans[i]);
}
int main() {
freopen("LG2664.in", "r", stdin);
freopen("LG2664.out", "w", stdout);
init();
solve();
#ifdef Qrsikno
debug("\nRunning time: %.3lf(s)\n", clock() * 1.0 / CLOCKS_PER_SEC);
#endif
return 0;
}
[LuoGu]P2664 树上游戏的更多相关文章
- Luogu P2664 树上游戏 dfs+树上统计
题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...
- luogu P2664 树上游戏(点分治)
点分治真是一个好东西.可惜我不会 这种要求所有路经的题很可能是点分治. 然后我就不会了.. 既然要用点分治,就想,点分治有哪些优点?它可以\(O(nlogn)\)遍历分治树的所有子树. 那么现在的问题 ...
- P2664 树上游戏
P2664 树上游戏 https://www.luogu.org/problemnew/show/P2664 分析: 点分治. 首先关于答案的统计转化成计算每个颜色的贡献. 1.计算从根出发的路径的答 ...
- 洛谷 P2664 树上游戏 解题报告
P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...
- ●洛谷P2664 树上游戏
题链: https://www.luogu.org/problemnew/show/P2664题解: 扫描线,线段树维护区间覆盖 https://www.luogu.org/blog/ZJ75211/ ...
- 洛谷P2664 树上游戏
https://www.luogu.org/problemnew/show/P2664 #include<cstdio> #include<algorithm> #includ ...
- 洛谷P2664 树上游戏(点分治)
传送门 题解 因为一个sb错误调了一个晚上……鬼晓得我为什么$solve(rt)$会写成$solve(v)$啊!!!一个$O(logn)$被我硬生生写成$O(n)$了竟然还能过$5$个点……话说还一直 ...
- 洛谷P2664 树上游戏(点分治)
题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...
- luogu P2644 树上游戏
一道点分难题 首先很自然的想法就是每种颜色的贡献可以分开计算,然后如果你会虚树就可以直接做了 点分也差不多,考虑每个分治重心的子树对它的贡献以及它对它子树的贡献 首先,处理一个\(cnt\)数组,\( ...
随机推荐
- iOS开发之---判断是否是手机号
iOS开发之---判断是否是手机号
- 利用python暴力破解ssh
# -*- coding:utf-8 -*- #python 2.7 import optparse,sys,threading import pexpect PROMPT = ['#','>' ...
- mysql 查询正在执行的事务以及等待锁 常用的sql语句
使用navicat测试学习: 首先使用set autocommit = 0;(取消自动提交,则当执行语句commit或者rollback执行提交事务或者回滚) 在打开一个执行update查询 正在 ...
- Arcgis Engine(ae)接口详解(2):featureClass查询
//属性查询~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //IQueryFilter代表查询条件,QueryFilterClass代表只限于属性查询(就是没有空间查询) ...
- the hard problems when writing a great connector; type cohersion, data partitioning and data locality to name a few
http://rosslawley.co.uk/introducing-a-new=mongodb-spark-connector/
- Android开发之开机自动启动应用
package com.raycloud.wolf.autostart; import android.content.BroadcastReceiver; import android.conten ...
- html5--6-68 实战前的准备工作:了解HTML5大纲算法
html5--6-68 实战前的准备工作:了解HTML5大纲算法 学习要点 了解HTML5大纲算法 在html5中有一个很重要的概念,叫做HTML5大纲算法(HTML5 Outliner),它的用途为 ...
- 一步一步学Silverlight 2系列(17):数据与通信之ADO.NET Data Services
概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...
- BZOJ_1915_[Usaco2010 Open]奶牛的跳格子游戏_DP+单调队列
BZOJ_1915_[Usaco2010 Open]奶牛的跳格子游戏_DP+单调队列 Description 奶牛们正在回味童年,玩一个类似跳格子的游戏,在这个游戏里,奶牛们在草地上画了一行N个格子, ...
- maven(二)创建一个maven的web项目中解决Cannot change version of project facet Dynamic web module to 2.5
我们用Eclipse创建Maven结构的web项目的时候选择了Artifact Id为maven-artchetype-webapp,由于这个catalog比较老,用的servlet还是2.3的,而一 ...