采蘑菇

Time Limit: 20 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  5
  1 2 3 2 3
  1 2
  1 3
  2 4
  2 5

Sample Output

  10
  9
  12
  9
  11

HINT

  

Main idea

  询问从以每个点为起始点时,各条路径上的颜色种类的和。

Solution

  我们看到题目,立马想到了O(n^2)的做法,然后从这个做法研究一下本质,我们确定了可以以点分治作为框架。

  我们先用点分治来确定一个center(重心)。然后计算跟这个center有关的路径。设现在要统计的是经过center,对x提供贡献的路径。

  我们先记录一个记录Sum[x]表示1~i-1子树中 颜色x 第一次出现的位置的那个点 的子树和,然后我们就利用这个Sum来解题。

  我们显然可以分两种情况来讨论:

  (1)统计center->x出现颜色的贡献
    显然,这时候,对于center->x这一段,直接像O(n^2)做法那样记录一个color表示到目前为止出现的颜色个数,然后加一下即可。再记录一个record表示当前可有的贡献和,一旦出现过一个颜色,那么这个颜色在1~i-1子树上出现第一次以下的点,对于x就不再提供贡献了,record减去Sum[这个颜色],然后这样深搜往下计算即可。

  (2)统计center->x没出现过的颜色的贡献
    显然,对于center->x上没出现过的颜色,直接往下深搜,一开始为record为(All - Sum[center]),一旦出现了一个颜色,record则减去这个Sum。同样表示不再提供贡献即可。

  我们这样做就可以求出每个子树前缀对于其的贡献了,倒着再做一边即可求出全部的贡献。统计x的时候,顺便统计一下center。可以满足效率,成功AC这道题。

Code

 #include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std; const int ONE = ;
const int INF = ;
const int MOD = 1e9+; int n,x,y;
int Val[ONE];
int next[ONE],first[ONE],go[ONE],tot;
int vis[ONE];
int Ans[ONE],Sum[ONE];
int All; int get()
{
int res,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} void Add(int u,int v)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v;
next[++tot]=first[v]; first[v]=tot; go[tot]=u;
} namespace Point
{
int center;
int Stack[ONE],top;
int total,Max,center_vis[ONE];
int num,V[ONE]; struct power
{
int size,maxx;
}S[ONE]; void Getsize(int u,int father)
{
S[u].size=;
S[u].maxx=;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || center_vis[v]) continue;
Getsize(v,u);
S[u].size += S[v].size;
S[u].maxx = max(S[u].maxx,S[v].size);
}
} void Getcenter(int u,int father,int total)
{
S[u].maxx = max(S[u].maxx,total-S[u].size);
if(S[u].maxx < Max)
{
Max = S[u].maxx;
center = u;
} for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || center_vis[v]) continue;
Getcenter(v,u,total);
}
} void Ad_sum(int u,int father)
{
if(!vis[Val[u]])
{
Stack[++top] = Val[u];
All += S[u].size; Sum[Val[u]] += S[u].size;
}
vis[Val[u]]++;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || center_vis[v]) continue;
Ad_sum(v,u);
}
vis[Val[u]]--;
} void Calc_in(int u,int father,int center,int Size,int f_time,int record)
{
if(!vis[Val[u]]) f_time++, record += Size, record -= Sum[Val[u]];
Ans[u] += record; Ans[center]+=f_time;
Ans[u] += f_time; vis[Val[u]] ++;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || center_vis[v]) continue;
Calc_in(v,u,center,Size,f_time,record);
}
vis[Val[u]] --;
} void Calc_not(int u,int father,int record)
{
if(!vis[Val[u]]) record -= Sum[ Val[u] ];
Ans[u] += record; vis[Val[u]] ++;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father || center_vis[v]) continue;
Calc_not(v,u,record);
}
vis[Val[u]] --;
} void Dfs(int u)
{
Max = n;
Getsize(u,);
Getcenter(u,,S[u].size);
Getsize(center,);
center_vis[center] = ; int num=; for(int e=first[center];e;e=next[e]) if(!center_vis[go[e]]) V[++num]=go[e]; for(int i=;i<=num;i++)
{
int v=V[i];
int Size = S[center].size - S[v].size - ;
vis[Val[center]] = ;
Calc_in(v,center,center, Size,,All - Sum[Val[center]] + Size);
vis[Val[center]] = ;
Ad_sum(v,center);
}
while(top) Sum[Stack[top--]]=; All=; for(int i=num;i>=;i--)
{
int v=V[i];
vis[Val[center]] = ;
Calc_not(v,center, All-Sum[Val[center]]);
vis[Val[center]] = ;
Ad_sum(v,center);
} while(top) Sum[Stack[top--]]=; All=;
for(int e=first[center];e;e=next[e])
{
int v=go[e];
if(center_vis[v]) continue;
Dfs(v);
}
} } int main()
{
n=get();
for(int i=;i<=n;i++) Val[i]=get(); for(int i=;i< n;i++)
{
x=get(); y=get();
Add(x,y);
} Point:: Dfs();
for(int i=;i<=n;i++)
printf("%d\n",Ans[i]+);
}

【Foreign】采蘑菇 [点分治]的更多相关文章

  1. [Luogu 2656] 采蘑菇

    Description 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采 ...

  2. 洛谷——P2656 采蘑菇

    P2656 采蘑菇 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次, ...

  3. 洛谷—— P2656 采蘑菇

    https://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连 ...

  4. 【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇

    歧义差评:但是和题意理解一样了之后细节依然处理了很久,说明还是水平不够…… 题目描述 Marisa来到了森林之中,看到了一排nn个五颜六色的蘑菇,编号从1-n1−n,这些蘑菇的颜色分别为col[1], ...

  5. F 采蘑菇的克拉莉丝

    这是一道树链剖分的题目: 很容易想到,我们在树剖后,对于操作1,直接单点修改: 对于答案查询,我们直接的时候,我们假设查询的点是3,那么我们在查询的时候可分为两部分: 第一部分:查找出除3这颗子树以外 ...

  6. Luogu P2656 采蘑菇

    尽管是缩点的习题,思路也是在看了题解后才明白的. 首先,每个强连通分量内的点都是一定互通的,也就是可以完全把这里面的边都跑满,摘掉所有能摘的蘑菇.那么,考虑给每一个强连通分量化为的新点一个点权,代表摘 ...

  7. [Luogu1119]采蘑菇

    题目大意: 给你一个无向图,点i在时间t[i]之前是不存在的,有q组询问,问你时间为t时从x到y的最短路. 点的编号按出现的时间顺序给出,询问也按照时间顺序给出. 思路: Floyd. Floyd的本 ...

  8. [Luogu2656]采蘑菇

    题目大意: 给你一个有向图,每条边有一个边权w以及恢复系数k, 你从s点出发乱走,经过某条边时会获得相应的收益w,而当第二次经过这条边时相应的收益为w*k下取整. 问你最大能获得的收益为多少? 思路: ...

  9. Wannafly Camp 2020 Day 2F 采蘑菇的克拉莉丝 - 树链剖分

    如果暴力维护,每次询问时需要对所有孩子做计算 考虑通过树剖来平衡修改与询问的时间,询问时计算重链和父树,轻链的贡献预先维护好,修改时则需要修改可能影响的轻链贡献,因为某个点到根的路径上轻重交替只有 \ ...

随机推荐

  1. 线程池ThreadPoolExecutor使用

    一.简介 线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int ...

  2. ubuntu apt-get 使用代理设置,坑爹。。

    网上流传的export http_proxy=http://yourproxyaddress:proxyport是行不通的,虽然改了之后wget一类的可以用.当然去改.bashrc也不会有效果. 真正 ...

  3. zabbix 2.2 调小监控值

    zabbix_agent默认disk下小于0%告警 调小到5% 组态 > 模板 选择需要的模板的触发器 例如 Template OS Windows 选择触发器 - 探索规则 - 触发器类型  ...

  4. Uniy 组件式泛型单例模式

    我们知道,在Unity中,所有对象脚本都必须继承MonoBehavior脚本,才能使用Unity内置的脚本功能; 通常我们可以用静态类来取代单例模式,但是静态类方法的缺点是,它们必须继承最底层的类-- ...

  5. LeetCode 876——链表的中间结点

    1. 题目 给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形 ...

  6. 文本向量化及词袋模型 - NLP学习(3-1)

    分词(Tokenization) - NLP学习(1) N-grams模型.停顿词(stopwords)和标准化处理 - NLP学习(2)   之前我们都了解了如何对文本进行处理:(1)如用NLTK文 ...

  7. windows下git hub的GUI软件配置与使用

    转载自:http://www.cnblogs.com/haore147/p/3618930.html   1. 安装两个软件 1 2 1. git的命令行程序--git for windows:htt ...

  8. [译]在SQL查询中如何映射(替换)查询的结果?

    问题来源: https://stackoverflow.com/questions/38567366/mapping-values-in-sql-select 有一个表格,就称它Plant,它有三列: ...

  9. sql 条件插入

    原普通插入语句: insert into seriestable_upload values(New.SeriesID,0); 加条件后:(当不存在该条数据插入) insert into custom ...

  10. 关于org.springframework.web.filter.CharacterEncodingFilter的学习

    介绍 org.springframework.web.filter.CharacterEncodingFilter 这是一个过滤器,是Spring在web请求中定义request和response的编 ...