洛谷 P2664 树上游戏 解题报告
P2664 树上游戏
题目描述
\(\text{lrb}\)有一棵树,树的每个节点有个颜色。给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量。以及\(sum_i=\sum\limits_{j=1}^ns(i,j)\)
现在他想让你求出所有的\(sum_i\)
输入输出格式
输入格式:
第一行为一个整数\(n\),表示树节点的数量
第二行为\(n\)个整数,分别表示\(n\)个节点的颜色\(c[1],c[2],\dots,c[n]\)
接下来\(n-1\)行,每行为两个整数\(x,y\),表示\(x\)和\(y\)之间有一条边
输出格式:
输出\(n\)行,第\(i\)行为\(sum[i]\)
说明
对于\(40\%\)的数据,\(n\le 2000\)
对于\(100\%\)的数据,\(1\le n,c[i]\le10^5\)
本辣鸡深深的认识到了自己的淀粉质写法有多么的诡异..
这个题在淀粉质上的思路还是比较简单的,就是写起来很烦人。
我的做法大致是
每次出去遍历子树时维护一个当前链颜色集合和一个过点分治根的每个颜色所属链的个数。然后每个点根据个数加一些本身颜色的贡献就可以了。注意要从左从右各做一遍。
说起来比较简单,但实际上还是要想一想的。
然后我拿\(map\)乐呵呵的维护颜色集合然后成功T飞
发现拿数组就可以了,但是最后要dfs去清空数组。
Code:
#include <cstdio>
#include <vector>
#include <map>
#include <cctype>
#define ll long long
const int N=1e5+10;
int read()
{
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
return x;
}
std::vector <int> Edge[N];
ll sum[N];
const int inf=0x3f3f3f3f;
int n,c[N],siz[N],del[N],mi,rt,lassiz,typ,sumnow;
void getroot(int now,int fa,int s)
{
int mx=0;
siz[now]=1;
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(del[v]||v==fa) continue;
getroot(v,now,s);
siz[now]+=siz[v];
mx=mx>siz[v]?mx:siz[v];
}
mx=mx>s-siz[now]?mx:s-siz[now];
if(mi>mx) rt=now,mi=mx;
}
int nowcolor[N];//存到根的颜色集合
ll lascolor[N],tlascolor[N];//存外面的链每种颜色在多少条链出现过
void dfs(int now,int fa,int totcolor,ll outsum)
{
siz[now]=1;int flag=0;
if(!nowcolor[c[now]])//如果到根第一次出现这个颜色
{
++totcolor,nowcolor[c[now]]=1;
outsum=outsum+lassiz-lascolor[c[now]];//有这么多条路径没有这种颜色
flag=1;
}
sum[now]+=outsum;
sum[now]=sum[now]-totcolor*typ;//减去统计自己与根的答案
sumnow+=totcolor;
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(del[v]||v==fa) continue;
dfs(v,now,totcolor,outsum);
siz[now]+=siz[v];
}
if(flag)//如果到根第一次出现这个颜色
{
nowcolor[c[now]]=0;
tlascolor[c[now]]+=1ll*siz[now];
}
}
void dfsin(int now,int fa)
{
int flag=0;
if(!nowcolor[c[now]])//如果到根第一次出现这个颜色
{
nowcolor[c[now]]=1;
flag=1;
}
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(del[v]||v==fa) continue;
dfsin(v,now);
}
if(flag)//如果到根第一次出现这个颜色
{
nowcolor[c[now]]=0;
lascolor[c[now]]+=1ll*siz[now];
}
}
void dfsclear(int now,int fa)
{
lascolor[c[now]]=0;
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(del[v]||v==fa) continue;
dfsclear(v,now);
}
}
void divide(int now,int s)
{
mi=inf;getroot(now,now,s);
del[now=rt]=1;
lascolor[c[now]]=1,typ=0,sumnow=1,lassiz=1,nowcolor[c[now]]=1;
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(del[v]) continue;
dfs(v,now,1,sumnow);
lascolor[c[now]]+=1ll*siz[v];
dfsin(v,now);
lassiz+=siz[v];
}
sum[now]=sum[now]+sumnow;
dfsclear(now,now);
lascolor[c[now]]=1,typ=1,sumnow=1,lassiz=1;
for(int i=Edge[now].size()-1;~i;i--)
{
int v=Edge[now][i];
if(del[v]) continue;
dfs(v,now,1,sumnow);
lascolor[c[now]]+=1ll*siz[v];
dfsin(v,now);
lassiz+=siz[v];
}
nowcolor[c[now]]=0;
dfsclear(now,now);
for(int i=0;i<Edge[now].size();i++)
{
int v=Edge[now][i];
if(!del[v]) divide(v,siz[v]);
}
}
int main()
{
n=read();
for(int i=1;i<=n;i++) c[i]=read();
for(int u,v,i=1;i<n;i++)
{
u=read(),v=read();
Edge[u].push_back(v);
Edge[v].push_back(u);
}
divide(1,n);
for(int i=1;i<=n;i++) printf("%lld\n",sum[i]);
return 0;
}
2018.12.4
洛谷 P2664 树上游戏 解题报告的更多相关文章
- ●洛谷P2664 树上游戏
题链: https://www.luogu.org/problemnew/show/P2664题解: 扫描线,线段树维护区间覆盖 https://www.luogu.org/blog/ZJ75211/ ...
- 洛谷 P3177 树上染色 解题报告
P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...
- 洛谷 P4705 玩游戏 解题报告
P4705 玩游戏 题意:给长为\(n\)的\(\{a_i\}\)和长为\(m\)的\(\{b_i\}\),设 \[ f(x)=\sum_{k\ge 0}\sum_{i=1}^n\sum_{j=1}^ ...
- 洛谷 P1057 传球游戏 解题报告
P1057 传球游戏 题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹 ...
- 洛谷 P1070 道路游戏 解题报告
P1070 道路游戏 题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有\(n\)个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依 ...
- 洛谷 P1199 三国游戏 解题报告
P1199 三国游戏 题目描述 小涵很喜欢电脑游戏,这些天他正在玩一个叫做<三国>的游戏. 在游戏中,小涵和计算机各执一方,组建各自的军队进行对战.游戏中共有\(N\)位武将(\(N\)为 ...
- 洛谷P2664 树上游戏(点分治)
传送门 题解 因为一个sb错误调了一个晚上……鬼晓得我为什么$solve(rt)$会写成$solve(v)$啊!!!一个$O(logn)$被我硬生生写成$O(n)$了竟然还能过$5$个点……话说还一直 ...
- 洛谷 P2123 皇后游戏 解题报告
P2123 皇后游戏 题意: 给定\(T\)组长为\(n\)的\(A\),\(B\)数组和\(C\)的计算方法,求一种排列方法,使最大的\(C\)最小化. 数据范围: \(1 \le T \le 10 ...
- 洛谷 P2041 分裂游戏 解题报告
P2041 分裂游戏 题目描述 有一个无限大的棋盘,棋盘左下角有一个大小为 n 的阶梯形区域,其中最左下角的那个格子里有一枚棋子.你每次可以把一枚棋子"分裂"成两枚棋子,分别放在原 ...
随机推荐
- c# 实体类怎么给LIST赋值,table转LIST
/// <summary> /// 缓存客服集合信息 /// </summary> public class model { /// <summary> /// 客 ...
- 搜索引擎ElasticSearch系列(二): ElasticSearch2.4.4 Head插件安装
一:ElasticSearch Head插件简介 elasticsearch-head is a web front end for browsing and interacting with an ...
- Windows隐藏账户
win7系统用户由于共享文件,会开启Guest来宾帐户,开启Guest来宾帐户后发现登录界面会显示guest帐户,但是只有在有密码的情况下才会显示,很多用户不喜欢显示guest帐户,那么Win7登录界 ...
- Zookeeper-----Zookeeper概述
一:Zookeeper的概念? ZooKeeper是一种分布式协调服务,用于管理大型主机.在分布式环境中协调和管理服务是一个复杂的过程.ZooKeeper通过其简单的架构和API解决了这个问题.Zoo ...
- 利用Pillow给图片添加重点框(适用UI自动化测试)
效果图 一个简单的例子 安装Pillow 在cmd窗口/终端输入: pip install pillow 如果被墙,下载巨慢的话,可以临时替换豆瓣源 pip install pillow -i htt ...
- smartgit 过期
进入到安装目录把Setting.xml 文件删除然后,再次打开就可以正常使用了.
- 2019CSUST集训队选拔赛题解(一)
来自ppq的毒瘤线段树 Sneakers Description 有一天喜欢买鞋的ppq和小伙伴来到了某一家球鞋店,球鞋店有n种球鞋,价格分别为ai,ppq在鞋店兜兜转转,发现鞋店老板会偶尔将某段 ...
- Python Pygame(5)绘制基本图形
最近很火一些简单图形构成的小游戏,这里介绍一些绘制图形的函数. 1.绘制矩形 rect(Surface,color,Rect,width=0) 第一个参数指定矩形绘制到哪个Surface对象上 第二个 ...
- “Hello World!”团队第七次Scrum立会
"Hello world!"团队召开第七次Scrum立会.博客内容: 1.会议时间 2.会议成员 3.会议地点 4.会议内容 5.Todo list 6.会议照片 7.燃尽图 一. ...
- 在windows和unbuntu上安装octave
windows安装octave 安装wiki Octave ftp库 从上述的库中可以找到对应的版本的octave的exe安装程序,或者是zip等的压缩包,建议直接下载对应系统的exe执行文件.安装. ...