题目

这真是一道神仙的一批的题目

定义\(s(i,j)\)表示从点\(i\)到点\(j\)经过的颜色数量

\[sum_i=\sum_{j=1}^ns(i,j)
\]

求出所有的\(sum_i\)

考虑点分治

对于一个点我们用两种方式来统计其答案

  1. 这个点作为分治重心时,分值区域内所有点到这个点贡献

  2. 这个点不是分治重心的时候,当前分治区域内其他子树到这个点的贡献

第一种贡献我们很好统计,点分治的时候把所有子树遍历一遍就好了

第二种就需要转换一下思路了,我们不能直接求\(s(i,j)\)了,我们应该求某一种颜色一共被数了多少次

我们开一个桶\(tax\),\(tax[i]\)表示\(i\)这种颜色控制的大小一共是多少,也就是这个颜色会被多少个终点数到,我们可以通过提前遍历好所有子树得到这个信息

每次进入一棵子树的时候,提前减掉这个子树的贡献,之后进入子树\(dfs\)就好了,如果一旦出现一种新颜色,显然这种颜色会被当前分治区域内所有点数上,更改一下贡献即可

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define maxn 100005
#define re register
#define inf 99999999
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
int x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
struct E{int v,nxt;}e[maxn<<1];
int col[maxn],head[maxn],vis[maxn],sum[maxn],mx[maxn];
int f[maxn],tax[maxn],d[maxn],st[maxn],tmp[maxn];
int num,n,m,now,S,rt,top;
LL ans,Ans[maxn],res;
std::vector<int> v[maxn],c[maxn];
inline void add(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
void getroot(int x,int fa) {
sum[x]=1,mx[x]=0;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
getroot(e[i].v,x);
sum[x]+=sum[e[i].v],mx[x]=max(mx[x],sum[e[i].v]);
}
mx[x]=max(mx[x],S-sum[x]);
if(mx[x]<now) now=mx[x],rt=x;
}
void getdis(int x,int fa,int now,int t) {
if(!f[col[x]]) now++;
if(!tmp[col[x]]) st[++top]=col[x];
tmp[col[x]]=1;sum[x]=1;f[col[x]]++;Ans[t]+=now;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
getdis(e[i].v,x,now,t);sum[x]+=sum[e[i].v];
}
if(f[col[x]]==1) d[col[x]]+=sum[x];
f[col[x]]--;
}
void find(int x,int fa) {
if(!f[col[x]]) ans-=tax[col[x]],ans+=res;
Ans[x]+=ans;f[col[x]]++;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]||e[i].v==fa) continue;
find(e[i].v,x);
}
if(f[col[x]]==1) ans-=res,ans+=tax[col[x]];
f[col[x]]--;
}
void dfs(int x) {
vis[x]=1;ans=0;f[col[x]]=1;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
top=0;getdis(e[i].v,0,1,x);
for(re int j=1;j<=top;j++)
if(st[j]!=col[x]) v[e[i].v].push_back(d[st[j]]),c[e[i].v].push_back(st[j]);
for(re int j=1;j<=top;j++)
if(st[j]!=col[x]) tax[st[j]]+=d[st[j]],ans+=d[st[j]];
for(re int j=1;j<=top;j++) tmp[st[j]]=0,d[st[j]]=0;
}
f[col[x]]=0;
ans+=S,tax[col[x]]=S;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
res=S-sum[e[i].v];
ans-=sum[e[i].v],tax[col[x]]-=sum[e[i].v];
for(re int j=0;j<v[e[i].v].size();j++)
ans-=v[e[i].v][j],tax[c[e[i].v][j]]-=v[e[i].v][j];
find(e[i].v,0);
for(re int j=0;j<v[e[i].v].size();j++)
ans+=v[e[i].v][j],tax[c[e[i].v][j]]+=v[e[i].v][j];
ans+=sum[e[i].v],tax[col[x]]+=sum[e[i].v];
}
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
for(re int j=0;j<v[e[i].v].size();j++)
tax[c[e[i].v][j]]-=v[e[i].v][j];
v[e[i].v].clear(),c[e[i].v].clear();
}
tax[col[x]]=0;
for(re int i=head[x];i;i=e[i].nxt) {
if(vis[e[i].v]) continue;
now=inf,S=sum[e[i].v],getroot(e[i].v,0),dfs(rt);
}
}
int main() {
n=read();int x,y;
for(re int i=1;i<=n;i++) col[i]=read();
for(re int i=1;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
S=n,now=inf,getroot(1,0);dfs(rt);
for(re int i=1;i<=n;i++) printf("%lld\n",Ans[i]+1ll);
return 0;
}

「LG2664 树上游戏」的更多相关文章

  1. LG2664 树上游戏

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

  2. 「HAOI2015树上染色」「树形DP」

    其实我还不大会树形DP 此题就当练手叭,缕一下思路就好 题目链接 BZOJ4033 题目大意就是给一棵树,对一部分点染成黑色,剩下的为白色,问所有同色点距离之和....... 简明扼要的题意,然额我不 ...

  3. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  4. Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏

    Vue+WebSocket+ES6+Canvas 制作「你画我猜」小游戏 转载 来源:jrainlau 链接:https://segmentfault.com/a/1190000005804860 项 ...

  5. LibreOJ #524. 「LibreOJ β Round #4」游戏

    二次联通门 : LibreOJ #524. 「LibreOJ β Round #4」游戏 /* LibreOJ #524. 「LibreOJ β Round #4」游戏 找找规律就会发现.. 当有X的 ...

  6. LibreOJ #6191. 「美团 CodeM 复赛」配对游戏

    二次联通门 : LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 /* LibreOJ #6191. 「美团 CodeM 复赛」配对游戏 概率dp */ #include <cs ...

  7. 「区间DP」「洛谷P1043」数字游戏

    「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...

  8. LOJ #6192. 「美团 CodeM 复赛」城市网络 (树上倍增)

    #6192. 「美团 CodeM 复赛」城市网络 内存限制:64 MiB 时间限制:500 ms 标准输入输出   题目描述 有一个树状的城市网络(即 nnn 个城市由 n−1n-1n−1 条道路连接 ...

  9. Note -「圆方树」学习笔记

    目录 圆方树的定义 圆方树的构造 实现 细节 圆方树的运用 「BZOJ 3331」压力 「洛谷 P4320」道路相遇 「APIO 2018」「洛谷 P4630」铁人两项 「CF 487E」Touris ...

随机推荐

  1. grunt-contrib-cssmin使用指南

    原文:http://riny.net/2014/grunt-cssmin/ grunt-contrib-cssmin v0.7.0 使用cssmin压缩css文件 Getting Started 这个 ...

  2. springmvc + spring + ibatis + mysql

    1.spring mvc 官网下载:https://repo.spring.io/webapp/#/artifacts/browse/simple/General/libs-release-local ...

  3. JMS - ActiveMQ的简单使用

    首先需要下载ActiveMQ,下面的链接给我们列出了所有版本:http://activemq.apache.org/download-archives.html每个版本为不同的OS提供了链接: 公司电 ...

  4. web.xml配置文件中async-supported报错解决

    项目中配置spring时async-supported报错: 是因为<async-supported>true</async-supported>是web.xml 3.0的新特 ...

  5. [android] 天气app布局练习(二)

    主要练习一下GridView MainActivity.java package com.example.weatherreport; import java.util.ArrayList; impo ...

  6. CentOS 7.2 安装 MySQL 5.6.24

    说明:由于甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此CentOS社区采用mysql的MariaDB分支的方式来避开这个风险. 所以需要先加入yum的仓库,才能利用yum来安装my ...

  7. Heka 最简单例子

    技术人员学习都是从简单例子开始的, Heka的应用也是从简单开始的.   需求: 监控一个日志文件的内容, 在标准输出显示出来.   操作步骤: 使用下载好或者编译好的 heka 已经编译好的 rel ...

  8. 三、Bean的初始化

    一.使用构造器实例化Bean:这是最简单的方式,Spring IOC容器既能使用默认空构造器也能使用有参构造器两种方式创建bean 空构造器 <bean name="bean1&quo ...

  9. 理解mouseover,mouseout,mouseenter,mouseleave

    mouseover定义和用法 当鼠标指针位于元素上方时,会发生 mouseover 事件. 该事件大多数时候会与 mouseout 事件一起使用. mouseover() 方法触发 mouseover ...

  10. Windows API 编程-----Windows NT 环境下禁止任务切换

    函数原型: BOOL WINAPI SystemParametersInfo( _In_ UINT uiAction, _In_ UINT uiParam, _Inout_ PVOID pvParam ...