「CF375D Tree and Queries」
\(dsu\ on\ tree\)的板子题了
\(dsu\ on\ tree\)本质上一种优秀通过轻重链剖分优化到\(O(nlogn)\)的暴力
一般用来解决没有修改的允许离线的子树查询问题
首先先来处理出每一个节点的重儿子
接下来按照如下的顺序统计
递归处理当前节点的所有轻儿子
递归处理重儿子
遍历一遍整棵子树,统计信息(但是不用访问当前点的重儿子)
如果这个节点是重儿子,就返回,否则的话就清空所有信息
所以第三步,不用访问当前点的重儿子就是因为在第四步的时候重儿子没有被清空
至于这道题我们数颜色的时候开一个树状数组,每次存储颜色的桶数量发生变化,就在树状数组里修改相应的位置
查一个后缀和就好了
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define re register
#define lowbit(x) ((x)&(-x))
#define maxn 100005
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;
}
int n,m,num,__,Son,tot;
struct Ask{int x,k,rk;}q[maxn];
struct E{int v,nxt;}e[maxn<<1];
int son[maxn],sum[maxn],deep[maxn],col[maxn];
int dfn[maxn],c[maxn],tax[maxn],Ans[maxn],head[maxn];
inline int cmp(Ask A,Ask B) {return dfn[A.x]<dfn[B.x];}
inline void C(int x,int y) {e[++num].v=y;e[num].nxt=head[x];head[x]=num;}
inline void add(int x,int val) {for(re int i=x;i;i-=lowbit(i)) c[i]+=val;}
inline int ask(int x) {int now=0;for(re int i=x;i<=n;i+=lowbit(i)) now+=c[i];return now;}
void dfs1(int x) {
sum[x]=1;int maxx=-1;
for(re int i=head[x];i;i=e[i].nxt) {
if(deep[e[i].v]) continue;
deep[e[i].v]=deep[x]+1,dfs1(e[i].v);
sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
void dfs2(int x) {
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x]&&son[x]!=e[i].v) dfs2(e[i].v);
if(son[x]) dfs2(son[x]);
dfn[x]=++__;
}
void calc(int x,int opt) {
if(tax[col[x]]) add(tax[col[x]],-1);
tax[col[x]]+=opt;
if(tax[col[x]]) add(tax[col[x]],1);
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x]&&Son!=e[i].v) calc(e[i].v,opt);
}
void dfs(int x,int opt) {
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x]&&son[x]!=e[i].v)
dfs(e[i].v,0);
if(son[x]) dfs(son[x],1);
Son=son[x];calc(x,1);Son=0;
while(q[tot].x==x) {
Ans[q[tot].rk]=ask(q[tot].k);tot++;
}
if(!opt) calc(x,-1);
}
int main() {
n=read(),m=read();
for(re int i=1;i<=n;i++) col[i]=read();
for(re int x,y,i=1;i<n;i++) x=read(),y=read(),C(x,y),C(y,x);
deep[1]=1,dfs1(1),dfs2(1);
for(re int i=1;i<=m;i++) q[i].rk=i,q[i].x=read(),q[i].k=read();
std::sort(q+1,q+m+1,cmp);tot=1;dfs(1,1);
for(re int i=1;i<=m;i++) printf("%d\n",Ans[i]);
return 0;
}
「CF375D Tree and Queries」的更多相关文章
- CF375D Tree and Queries
题意翻译 给出一棵 n 个结点的树,每个结点有一个颜色 c i . 询问 q 次,每次询问以 v 结点为根的子树中,出现次数 ≥k 的颜色有多少种.树的根节点是1. 感谢@elijahqi 提供的翻译 ...
- CF375D Tree and Queries(dsu on tree)
思路 dsu on tree的板子,可惜人傻把 for(int i=fir[u];i;i=nxt[i]) 打成 for(int i=fir[u];i<=n;i++) 调了两个小时 这题要求维护& ...
- CF375D Tree and Queries 题解
感觉CF的题目名都好朴素的样子 你谷链接 首先这题显然是个dsu on tree 但是我不会. 其次这题显然是个莫队.这我会啊! 然后会发现好像不是很对劲.因为每次询问都有一个k,貌似和传统的莫队数颜 ...
- 【题解】 Luogu CF375D Tree and Queries
原题传送门 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 我博客中对莫队的详细介绍 莫队好题 我一上来想写线段树,随后觉得不好写并弃坑 我们可以看见没有修改操作,钦定莫队 但这是在树上,所以不能 ...
- cf375D. Tree and Queries(莫队)
题意 题目链接 给出一棵 n 个结点的树,每个结点有一个颜色 c i . 询问 q 次,每次询问以 v 结点为根的子树中,出现次数 ≥k 的颜色有多少种.树的根节点是1. Sol 想到了主席树和启发式 ...
- 【题解】CF375D Tree and Queries
Link \(\text{Solution:}\) 讲实话这题有点烦,不知道为啥改了下\(\text{dfs}\)就过了--原版本\(dfs\)好像没啥错啊-- 其实对于子树问题,我们求出原来树的\( ...
- #10471. 「2020-10-02 提高模拟赛」灌溉 (water)
题面:#10471. 「2020-10-02 提高模拟赛」灌溉 (water) 假设只有一组询问,我们可以用二分求解:二分最大距离是多少,然后找到深度最大的结点,并且把它的\(k\)倍祖先的一整子树删 ...
- 众安「尊享e生」果真牛的不可一世么?
近日,具有互联网基因的.亏损大户(成立三年基本没盈利,今年二季度末亏损近4亿,你能指望它多厉害?).财产险公司—众安推出“尊享e生”中高端医疗保险(财险公司经营中高端医疗真的很厉害?真的是中高端医疗险 ...
- XCActionBar 「Xcode 中的 Alfred」
下载地址:https://github.com/pdcgomes/XCActionBar 基本命令: (1)「command+shift+8」或者双击「command」键可以打开「动作输入框窗口」 ( ...
随机推荐
- 【转】HttpURLConnection用法详解
原文链接:http://www.blogjava.net/supercrsky/articles/247449.html 针对JDK中的URLConnection连接Servlet的问题,网上有虽然有 ...
- 关于windowsServer编程
1.关于windowsServer编程
- 微信小程序开发框架整理
目前除了原生的微信小程序开发外,各大厂商陆续造了自己的开发框架,现整理如下: WePY 腾讯官方开源的小程序组件化开发框架,目前有15K+Star ,一直在更新着,社区活跃,掉坑能快速的找到方法爬出来 ...
- 超时重试(一)ajax
我们使用jquery的ajax,超时重试可以采用两种方式,一种是配置ajax的timeout的参数,另一种就是以setTimeout定时器的方式实现: 1)timeout参数配置方式 var xhr ...
- 微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆
原创声明:本文为本人原创作品,绝非他处转账,转载请联系博主 从接触公众号到现在,开发维护了2个公众号,开发过程中遇到很多问题,现在把部分模块功能在这备案一下,做个总结也希望能给其他人帮助 工欲善其事, ...
- HTML5数据存储方案data与jQuery数据存储方案$.data()的区别
我们先看下$.fn.data()的使用,这个和$.data()是不一样的,前者是和某个jquery对象相关,后者则是全局方法.主要有data()和removeData()这2个实例方法.通过下面的例子 ...
- VS code 自定义快捷输入
本文是从简书复制的, markdown语法可能有些出入, 想看"正版"和更多内容请关注 简书: 小贤笔记 位置 ctrl+shift+p 搜索: snippets 输入类型: 比如 ...
- js Array数组对象常见方法总结
Array对象一般用来存储数据. 其常用的方法包括: 1.concat()方法 concat() 方法用于合并两个或多个数组.它不会更改现有数组,而是返回一个新数组. 例如: var arr1=[1, ...
- <Android Framework 之路>BootAnimation(1)
介绍 开机动画,BootAnimation,就是Android手机开机郭晨各种以一个展示给用户的界面,实际是一个多个帧组成的动画,在界面上进行一帧一帧的播放,形成开机动画的效果. 本文针对Androi ...
- 日常捕获的野生知识 - javascript 与 类
javascript 并不提供类这样方便实用的面向对象类型,今天学习到了,直接上代码: <!DOCTYPE html> <html lang="en"> & ...