Boring counting

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)

Problem Description
In this problem we consider a rooted tree with N vertices. The vertices are numbered from 1 to N, and vertex 1 represents the root. There are integer weights on each vectice. Your task is to answer a list of queries, for each query, please tell us among all the vertices in the subtree rooted at vertice u, how many different kinds of weights appear exactly K times?
 
Input
The first line of the input contains an integer T( T<= 5 ), indicating the number of test cases.
For each test case, the first line contains two integers N and K, as described above. ( 1<= N <= 105, 1 <= K <= N )
Then come N integers in the second line, they are the weights of vertice 1 to N. ( 0 <= weight <= 109 )
For next N-1 lines, each line contains two vertices u and v, which is connected in the tree.
Next line is a integer Q, representing the number of queries. (1 <= Q <= 105)
For next Q lines, each with an integer u, as the root of the subtree described above.
 
Output
For each test case, output "Case #X:" first, X is the test number. Then output Q lines, each with a number -- the answer to each query.

Seperate each test case with an empty line.

 
Sample Input
1
3 1
1 2 2
1 2
1 3
3
2
1
3
 
Sample Output
Case #1:
1
1
1
 
Author
fish@UESTC_Oblivion
 
Source
题意:给你一棵树,n个节点,以1为根,每个节点有一个权值w;
   q个询问,每个询问问,以该点为根的子树下某个权值出现k次的个数;
思路:首先w很大,用map会超时;需要离散化一下;
   处理子树问题,利用dfs序,改成区间处理;
   区间处理权值出现k次的树,利用莫队得到答案;
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-14
const int N=1e5+,M=1e6+,inf=1e9+;
const ll INF=1e18+,mod=;
struct is
{
int v,nex;
}edge[N<<];
int head[N<<],edg,in[N],out[N],tot,pos[N],w[N];
vector<int>l;
int a[N],flag[N];
void add(int u,int v)
{
edg++;
edge[edg].v=v;
edge[edg].nex=head[u];
head[u]=edg;
}
void dfs(int u,int fa)
{
in[u]=++tot;
for(int i=head[u];i!=-;i=edge[i].nex)
{
int v=edge[i].v;
if(v==fa)continue;
dfs(v,u);
}
out[u]=tot;
}
struct hh
{
int l,r,now;
bool operator <(const hh b)
{
if(pos[l]!=pos[b.l])
return pos[l]<pos[b.l];
return r<b.r;
}
}p[N];
int ans[N],mp[N],z[N];
void add(int pos)
{
z[mp[a[pos]]]--;
mp[a[pos]]++;
z[mp[a[pos]]]++;
}
void del(int pos)
{
z[mp[a[pos]]]--;
mp[a[pos]]--;
z[mp[a[pos]]]++;
}
void init(int n)
{
l.clear();
memset(mp,,sizeof(mp));
memset(z,,sizeof(z));
int s=(int)(sqrt(n));
for(int i=;i<=n;i++)
pos[i]=(i-)/s+;
memset(head,-,sizeof(head));
memset(a,,sizeof(a));
edg=;
tot=;
}
int main()
{
int T,cas=;
scanf("%d",&T);
while(T--)
{
if(cas!=)
printf("\n");
int n,k;
scanf("%d%d",&n,&k);
init(n);
for(int i=;i<=n;i++)
scanf("%d",&w[i]),l.push_back(w[i]);
sort(l.begin(),l.end());
for(int i=;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(,-);
for(int i=;i<=n;i++)
flag[in[i]]=i;
for(int i=;i<=n;i++)
a[i]=lower_bound(l.begin(),l.end(),w[flag[i]])-l.begin();
int q;
scanf("%d",&q);
for(int i=;i<=q;i++)
{
int x;
scanf("%d",&x);
p[i].l=in[x];
p[i].r=out[x];
p[i].now=i;
}
sort(p+,p++q);
int L=,R=;
for(int i=;i<=q;i++)
{
//cout<<p[i].l<<" "<<p[i].r<<" "<<p[i].now<<endl;
while(L<p[i].l)
{
del(L);
L++;
}
while(L>p[i].l)
{
L--;
add(L);
}
while(R>p[i].r)
{
del(R);
R--;
}
while(R<p[i].r)
{
R++;
add(R);
}
ans[p[i].now]=z[k];
}
printf("Case #%d:\n",cas++);
for(int i=;i<=q;i++)
printf("%d\n",ans[i]);
}
return ;
}

hdu 4358 Boring counting dfs序+莫队+离散化的更多相关文章

  1. HDU 4358 Boring counting dfs序+莫队算法

    题意:N个节点的有根树,每个节点有一个weight.有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种. 这是第一次写莫队算法,之前也只是偶有耳闻. 看了别人的代码打的,还是贴上 ...

  2. HDU 4358 Boring counting(莫队+DFS序+离散化)

    Boring counting Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others) ...

  3. hdu 4358 Boring counting 离散化+dfs序+莫队算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意:以1为根节点含有N(N <= 1e5)个结点的树,每个节点有一个权值(weight ...

  4. HDU - 4358 Boring counting (dsu on tree)

    Boring counting: http://acm.hdu.edu.cn/showproblem.php?pid=4358 题意: 求一棵树上,每个节点的子节点中,同一颜色出现k次 的 个数. 思 ...

  5. Codeforces 375D - Tree and Queries(dfs序+莫队)

    题目链接:http://codeforces.com/contest/351/problem/D 题目大意:n个数,col[i]对应第i个数的颜色,并给你他们之间的树形关系(以1为根),有m次询问,每 ...

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

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

  7. CF600E Lomsat gelral (dfs序+莫队)

    题面 题解 看到网上写了很多DSU和线段树合并的题解,笔者第一次做也是用的线段树合并,但在原题赛的时候却怕线段树合并调不出来,于是就用了更好想更好调的莫队. 这里笔者就说说莫队怎么做吧. 我们可以通过 ...

  8. HDU - 4358 Boring counting (树上启发式合并/线段树合并)

    题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> usin ...

  9. HDU 4358 Boring counting 树状数组+思路

    研究了整整一天orz……直接上官方题解神思路 #include <cstdio> #include <cstring> #include <cstdlib> #in ...

随机推荐

  1. canvas 线条不清楚的问题

    对于canvas 画出的1px线条不清楚的问题, 一般是坐标点+0.5像素的问题, 但是有时要考虑viewpoint的问题,让canvas的width = 980,同时viewpoint = 980 ...

  2. c语言-交换两个整数

    使用c来写一个函数来实现交换两个整数. 第一种 一般的方法,引用中间变量,方便快捷. void swap(int *a, int *b) { int tmp = *a; *a = *b; *b = t ...

  3. 《linux内核设计与实现》读书笔记第三章

    第3章 进程管理 3.1 进程 1.进程 进程就是处于执行期的程序. 进程包括: 可执行程序代码 打开的文件 挂起的信号 内核内部数据 处理器状态 一个或多个具有内存映射的内存地址空间 一个或多个执行 ...

  4. C++ 安全拼接字符串函数

    void SafeStrAppend(char buf[], const uint32_t maxBufSize, uint32_t &offset, const char *format, ...

  5. angularJS支持的事件

    AngularJS提供可与HTML控件相关联的多个事件.例如ng-click通常与按钮相关联.以下是AngularJS支持的事件. ng-click ng-dbl-click ng-mousedown ...

  6. PHP5与MySQL数据库操作

    1 建立数据库表:  2 读取数据 2.1 建立01.php 2.2 建立member.php  3 修改数据 3.1 建立level.php(修改数据) 3.2 建立up_level.php  4 ...

  7. PHP---------PHP函数里面的static静态变量

    工作一年了,一年里很少用到static这个关键词,不管是类里面还是方法里面基本都没怎么用过.平时看到类里面有这个都没什么好奇的,今天在函数里面看到了这个,就去百度了一下. <?phpfuncti ...

  8. request.get request.GET……

    发现他们是不同的. 报错: AttributeError at /add/ 'WSGIRequest' object has no attribute 'get' Request Method: GE ...

  9. C# 实现 微软WebRequestMethods.Ftp类中的FTP操作功能

    先奉献一个测试地址,ftp内的文件请勿删除,谢谢 FtpEntity fe = "); 由于代码量较多,只抽出一部分,详细代码请移步  ftp://wjshan0808.3vhost.net ...

  10. Communication 交流

    1:请不要立马抗拒别人的观点,先沉默下来思考,在做出回应. 2:在与别人交流的时候,请尽量先让别人同意你的观点,找到共同点,让别人回答 "是";