感觉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 题解的更多相关文章

  1. 【题解】 Luogu CF375D Tree and Queries

    原题传送门 这道题要用树链剖分,我博客里有对树链剖分的详细介绍 我博客中对莫队的详细介绍 莫队好题 我一上来想写线段树,随后觉得不好写并弃坑 我们可以看见没有修改操作,钦定莫队 但这是在树上,所以不能 ...

  2. 【题解】CF375D Tree and Queries

    Link \(\text{Solution:}\) 讲实话这题有点烦,不知道为啥改了下\(\text{dfs}\)就过了--原版本\(dfs\)好像没啥错啊-- 其实对于子树问题,我们求出原来树的\( ...

  3. CF375D Tree and Queries

    题意翻译 给出一棵 n 个结点的树,每个结点有一个颜色 c i . 询问 q 次,每次询问以 v 结点为根的子树中,出现次数 ≥k 的颜色有多少种.树的根节点是1. 感谢@elijahqi 提供的翻译 ...

  4. 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++) 调了两个小时 这题要求维护& ...

  5. 「CF375D Tree and Queries」

    题目 \(dsu\ on\ tree\)的板子题了 \(dsu\ on\ tree\)本质上一种优秀通过轻重链剖分优化到\(O(nlogn)\)的暴力 一般用来解决没有修改的允许离线的子树查询问题 首 ...

  6. cf375D. Tree and Queries(莫队)

    题意 题目链接 给出一棵 n 个结点的树,每个结点有一个颜色 c i . 询问 q 次,每次询问以 v 结点为根的子树中,出现次数 ≥k 的颜色有多少种.树的根节点是1. Sol 想到了主席树和启发式 ...

  7. [Codeforces Round #221 (Div. 1)][D. Tree and Queries]

    题目链接:375D - Tree and Queries 题目大意:给你一个有n个点的树,每个点都有其对应的颜色,给出m次询问(v,k),问v的子树中有多少种颜色至少出现k次 题解:先对所有的询问进行 ...

  8. CodeForces 375D Tree and Queries 莫队||DFS序

    Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间 ...

  9. Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

    题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问$vj, kj$ 你需要回答在以$vj$为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少 ...

随机推荐

  1. 装配Bean的三种方式

    一.装配Bean就是在xml写一个Bean标签:装配完Bean,还需要读取xml配置文件创建Spring容器来创建对象: 1.new 实现类方式 正常的三种创建Bean容器的方法都可以根据装配的Bea ...

  2. python模块--collections(容器数据类型)

    Counter类(dict的子类, 计数器) 方法 返回值类型 说明 __init__ Counter 传入可迭代对象, 会对对象中的值进行计数, 值为键, 计数为值 .elements() 迭代器 ...

  3. Java 扫描识别条形码图片

    1.条形码扫描识别的实现方法及步骤 本文以Java代码示例介绍如何来扫描和识别条形码图片.这里使用免费条码工具 Free Spire.Barcode for Java,调用BarcodeScanner ...

  4. Linux之crontab命令

    简介 通过crontab 命令,我们可以在固定的间隔时间执行指定的系统指令或 shell 脚本.时间间隔的单位可以 是分钟.小时.日.月.周及以上的任意组合.这个命令非常适合周期性的日志分析或数据备份 ...

  5. 【多线程】Android多线程学习笔记——线程池

    Java线程池采用了享元设计模式,在系统中维持一定数量的线程,用于处理异步或并发需求,在平时处理异步或并发任务时被广泛使用.这里基于JDK1.8和Android28来整理一些关于线程池的知识点. 一. ...

  6. 【noip1998】题解:2的幂次方

    思路:设递归函数dfs(x)用于输出x的幂次方 最容易的思路:0不输出,1输出为2(0),2输出2,剩下的递归执行. 每一次递归:例如7,拆分为4+3,先拆出最大的是2的次方的数出来,输出4,再把3分 ...

  7. Shell条件判断(6)- 多重条件判断

    多重条件判断 多个条件判断一起使用 测试选项 作用 判断1 -a 判断2 逻辑与,判断1和判断2都成立,最终的结果才为真 判断1 -o 判断2 逻辑或,判断1和判断2有一个成立,最终的结果就为真 ! ...

  8. PKI及SSL协议分析PKI及SSL协议分析

    任务一:搭建CA服务器 本任务初步了解CA服务器的原理和配置过程.操作都在CA服务器上. 1.远程桌面方式登录到CA服务器,在CMD下查看本机IP地址: 2.安装证书服务 依次点击:"开始& ...

  9. ubuntu提示:无法获得锁 /var/lib/dpkg/lock-frontend - open (11: 资源暂时不可用)

    root@uni-virtual-machine:/home/uni# apt install apt-transport-https ca-certificates curl software-pr ...

  10. php stream 流封装协议

    http://php.net/manual/wrappers.php 过程: 1. 开始通信 2. 读取数据 3. 写入数据 4. 结束通信 usage: * 读写文件系统 <?php $han ...