CF375D Tree and Queries 题解
感觉CF的题目名都好朴素的样子
首先这题显然是个dsu on tree 但是我不会。
其次这题显然是个莫队。这我会啊!
然后会发现好像不是很对劲。因为每次询问都有一个k,貌似和传统的莫队数颜色有点不一样。
本蒟蒻看到这里的时候内心是崩溃的。然后就看了一眼题解。
然后我就迷惑了。震惊,前缀和还可以O(1)修改,活到爆!
然后经过郭神的一番论证以后,我惊讶的发现,这个题还真能O(1)修改前缀和。
首先,两个数组。sum[i]表示出现次数大于i的颜色的数量。val[i]表示颜色i的出现次数。
那么考虑莫队做法,当上一个询问的答案转移到当下的答案时,我们假设颜色i的数量要++。那么sum[val[i]+1]++;
但是会发现,出现次数是(val[i]+1)的颜色数量+1,而对应的,出现次数是(val[i])的颜色数量就要-1。也就是说,每次对颜色的修改,只会涉及到sum数组的单点,而不会涉及到前缀(或后缀)。
弄清楚这个,代码就很简单了。做个dfn序,跑普通莫队即可。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
#define gc() (p1 == p2 ? (p2 = buf + fread(p1 = buf, 1, 1 << 20, stdin), p1 == p2 ? EOF : *p1++) : *p1++)
#define read() ({ register int x = 0, f = 1; register char c = gc(); while(c < '0' || c > '9') { if (c == '-') f = -1; c = gc();} while(c >= '0' && c <= '9') x = x * 10 + (c & 15), c = gc(); f * x; })
char buf[1 << 20], *p1, *p2;
struct node{
int to,next;
}edge[maxn<<1];
int n,cnt,Time,m,ss;
int size[maxn],head[maxn],dfn[maxn],a[maxn],w[maxn],belong[maxn],sum[maxn],res[maxn],val[maxn];
struct Q{
int l,r,data,k;
}b[maxn];
void add(int from,int to){
edge[++cnt].to=to;
edge[cnt].next=head[from];
head[from]=cnt;
}
void dfs1(int u,int f){
size[u]=1;
dfn[u]=++Time;
w[Time]=a[u];
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==f) continue;
dfs1(v,u);
size[u]+=size[v];
}
}
bool cmp(Q x,Q y){
return belong[x.l]!=belong[y.l] ? x.l<y.l : belong[x.l]&1 ? x.r<y.r : x.r>y.r ;
}
void Solve(){
n=read(); m=read();
ss=sqrt(n);
for(int i=1;i<=n;++i) a[i]=read();
for(int i=1;i<=n;++i) belong[i]=(i-1)/ss+1;
for(int i=1,x,y;i<n;++i) {
x=read();
y=read();
add(x,y);
add(y,x);
}
dfs1(1,0);
for(int i=1,x;i<=m;++i){
x=read();
b[i].k=read();
b[i].data=i;
b[i].l=dfn[x];
b[i].r=dfn[x]+size[x]-1;
}
sort(b+1,b+m+1,cmp);
int l=1,r=0,ans=0;
for(int i=1;i<=m;++i){
while(l>b[i].l){
--l;
val[w[l]]++;
sum[val[w[l]]]++;
}
while(r<b[i].r){
++r;
val[w[r]]++;
sum[val[w[r]]]++;
}
while(l<b[i].l){
sum[val[w[l]]]--;
val[w[l]]--;
l++;
}
while(r>b[i].r){
sum[val[w[r]]]--;
val[w[r]]--;
r--;
}
res[b[i].data]=sum[b[i].k];
}
for(int i=1;i<=m;++i) printf("%d\n",res[i]);
}
int main(){
Solve();
return 0;
}
CF375D Tree and Queries 题解的更多相关文章
- 【题解】 Luogu CF375D Tree and Queries
原题传送门 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 我博客中对莫队的详细介绍 莫队好题 我一上来想写线段树,随后觉得不好写并弃坑 我们可以看见没有修改操作,钦定莫队 但这是在树上,所以不能 ...
- 【题解】CF375D Tree and Queries
Link \(\text{Solution:}\) 讲实话这题有点烦,不知道为啥改了下\(\text{dfs}\)就过了--原版本\(dfs\)好像没啥错啊-- 其实对于子树问题,我们求出原来树的\( ...
- 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」
题目 \(dsu\ on\ tree\)的板子题了 \(dsu\ on\ tree\)本质上一种优秀通过轻重链剖分优化到\(O(nlogn)\)的暴力 一般用来解决没有修改的允许离线的子树查询问题 首 ...
- cf375D. Tree and Queries(莫队)
题意 题目链接 给出一棵 n 个结点的树,每个结点有一个颜色 c i . 询问 q 次,每次询问以 v 结点为根的子树中,出现次数 ≥k 的颜色有多少种.树的根节点是1. Sol 想到了主席树和启发式 ...
- [Codeforces Round #221 (Div. 1)][D. Tree and Queries]
题目链接:375D - Tree and Queries 题目大意:给你一个有n个点的树,每个点都有其对应的颜色,给出m次询问(v,k),问v的子树中有多少种颜色至少出现k次 题解:先对所有的询问进行 ...
- CodeForces 375D Tree and Queries 莫队||DFS序
Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间 ...
- Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)
题目链接 Tree and Queries 题目大意 给出一棵树和每个节点的颜色.每次询问$vj, kj$ 你需要回答在以$vj$为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少 ...
随机推荐
- 装配Bean的三种方式
一.装配Bean就是在xml写一个Bean标签:装配完Bean,还需要读取xml配置文件创建Spring容器来创建对象: 1.new 实现类方式 正常的三种创建Bean容器的方法都可以根据装配的Bea ...
- python模块--collections(容器数据类型)
Counter类(dict的子类, 计数器) 方法 返回值类型 说明 __init__ Counter 传入可迭代对象, 会对对象中的值进行计数, 值为键, 计数为值 .elements() 迭代器 ...
- Java 扫描识别条形码图片
1.条形码扫描识别的实现方法及步骤 本文以Java代码示例介绍如何来扫描和识别条形码图片.这里使用免费条码工具 Free Spire.Barcode for Java,调用BarcodeScanner ...
- Linux之crontab命令
简介 通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell 脚本.时间间隔的单位可以 是分钟.小时.日.月.周及以上的任意组合.这个命令非常适合周期性的日志分析或数据备份 ...
- 【多线程】Android多线程学习笔记——线程池
Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...
- 【noip1998】题解:2的幂次方
思路:设递归函数dfs(x)用于输出x的幂次方 最容易的思路:0不输出,1输出为2(0),2输出2,剩下的递归执行. 每一次递归:例如7,拆分为4+3,先拆出最大的是2的次方的数出来,输出4,再把3分 ...
- Shell条件判断(6)- 多重条件判断
多重条件判断 多个条件判断一起使用 测试选项 作用 判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果才为真 判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真 ! ...
- PKI及SSL协议分析PKI及SSL协议分析
任务一:搭建CA服务器 本任务初步了解CA服务器的原理和配置过程.操作都在CA服务器上. 1.远程桌面方式登录到CA服务器,在CMD下查看本机IP地址: 2.安装证书服务 依次点击:"开始& ...
- ubuntu提示:无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)
root@uni-virtual-machine:/home/uni# apt install apt-transport-https ca-certificates curl software-pr ...
- php stream 流封装协议
http://php.net/manual/wrappers.php 过程: 1. 开始通信 2. 读取数据 3. 写入数据 4. 结束通信 usage: * 读写文件系统 <?php $han ...