[Codeforces375D]Tree and Queries(莫队算法)

题意:给定一棵树,每个节点有颜色,对于每个询问(u,k)询问以u为根节点的子树下有多少种颜色出现次数>=k

因为是子树,跟dfs序有关,转化为一段区间,可以用莫队算法求解

直接用一个数组统计出现次数>=k的颜色

Code

#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 100010
using namespace std;

int n,m,A[N],bl[N],Ans[N],dfn[N],sum[N],tot,head[N],sz[N],col[N],tw[N];
struct node{int to,nex;}e[N*2];
struct info{
	int l,r,k,id;
	friend bool operator <(info a,info b){
		return (bl[a.l]==bl[b.l])?a.r<b.r:a.l<b.l;
	}
}q[N];

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}

void upd(int x,int d){
	if(d>0) sum[++col[tw[x]]]++;
	else sum[col[tw[x]]--]--;
}

void Link(int u,int v){
	e[++tot].nex=head[u];e[tot].to=v;head[u]=tot;
}

void dfs(int u,int fa){
	dfn[u]=++tot,sz[u]=1,tw[tot]=A[u];
	for(int i=head[u];i;i=e[i].nex)
		if(e[i].to!=fa) dfs(e[i].to,u),sz[u]+=sz[e[i].to];
}

int main(){
	n=read(),m=read();int blo=sqrt(n);
	for(int i=1;i<=n;++i) A[i]=read(),bl[i]=i/blo+1;
	for(int i=1;i<n;++i){
		int u=read(),v=read();
		Link(u,v),Link(v,u);
	}
	tot=0,dfs(1,0);
	for(int i=1;i<=m;++i){
		int u=read(),k=read();
		q[i]=(info){dfn[u],dfn[u]+sz[u]-1,k,i};
	}
	sort(q+1,q+m+1);
	for(int i=1,l=1,r=0;i<=m;++i){
		for(;l<q[i].l;l++) upd(l,-1);
		for(;l>q[i].l;l--) upd(l-1,1);
		for(;r<q[i].r;r++) upd(r+1,1);
		for(;r>q[i].r;r--) upd(r,-1);
		Ans[q[i].id]=sum[q[i].k];
	}
	for(int i=1;i<=m;printf("%d\n",Ans[i++]));
	return 0;
}

原文地址:https://www.cnblogs.com/void-f/p/9092454.html

时间: 2024-07-30 12:52:52

[Codeforces375D]Tree and Queries(莫队算法)的相关文章

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

Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间,然后就是开一个数据记录下出现次数为k次的颜色数目,查询的时候直接返回这个数组中的对应的值就行了. 注意的就是记得将节点的颜色传递给dfs序对应位置的颜色. 这个忘记了找了好久的bug. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3

BZOJ 2589 Spoj 10707 Count on a tree II 强制在线莫队算法(TLE)

题目大意:给定一棵树,每个节点有一个颜色,多次询问某条路径上颜色数量,强制在线 正解是块状数组,强制在线莫队会TLE到死,想AC这道题的不用看了 如果朴素的跑树上莫队其实并不难- - 但是强制在线 因此我们可以考虑强制在线莫队算法 将树分成O(n^1/3)块,每块大小O(n^2/3) 记录每两块之间的答案.每种颜色的出现次数和哪些点被记录到了答案中 每次查询先找到两端点所在块的端点的答案,然后暴力用莫队转移即可 空间复杂度O(n^1/3)*O(n^1/3)*O(n)=O(n^5/3) 预处理时间

莫队算法良心讲解

问题:有n个数组成一个序列,有m个形如询问L, R的询问,每次询问需要回答区间内至少出现2次的数有哪些. 朴素的解法需要读取O(nm)次数.如果使用STL的Map来保存出现的次数,每次需要O(nmlogn)的复杂度.有没有更快的方法呢? 注意到询问并没有强制在线,因此我们可以使用离线方法.注意到一点,如果我们有计算完[L, R]的map,那么[L - 1, R].[L + 1, R].[L, R - 1].[L, R + 1]都能够在O(logn)的复杂度得出.是否能安排适当的询问顺序,使得每次

莫队算法小结(Markdown版)

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉 好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m个询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为0则输出01 仔细观察发现,令x表示x这个值出现的次

XOR and Favorite Number(莫队算法+分块)

E. XOR and Favorite Number time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pai

CodeFroce Round 340 div2 E XOR and Favorite Number【莫队算法】

题面: Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l?≤?i?≤?j?≤?r and the xor of the numbers ai,?ai?

[转载] 莫队算法

FROM: http://www.cnblogs.com/CsOH/p/5904430.html 问题:有n个数组成一个序列,有m个形如询问L, R的询问,每次询问需要回答区间内至少出现2次的数有哪些. 朴素的解法需要读取O(nm)次数.如果数据范围小,可以用数组,时间复杂度为O(nm).如果使用STL的Map来保存出现的次数,则需要O(nmlogn)的复杂度.有没有更快的方法呢? 注意到询问并没有强制在线,因此我们可以使用离线方法.注意到一点,如果我们有计算完[L, R]时的"中间变量&quo

D. Powerful array 离线+莫队算法 给定n个数,m次查询;每次查询[l,r]的权值; 权值计算方法:区间某个数x的个数cnt,那么贡献为cnt*cnt*x; 所有贡献和即为该区间的值;

D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input standard input output standard output An array of positive integers a1,?a2,?...,?an is given. Let us consider its arbitrary subarray al,?al?+?1...,?ar, where 1?

莫队算法小结

唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为则输出0/1 仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区