HDU 4358 莫队算法+dfs序+离散化

Boring counting

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 98304/98304 K (Java/Others)
Total Submission(s): 2808    Accepted Submission(s): 826


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
 
题意:给你一个树  每个节点都有一个权值   q个询问 问x的子树中有多少种不同的权值出现了k次
题解:第一题莫队 莫队算法 正如莫涛本人而言这种方法是处理一类无修改的离线区间询问问题的  dfs序将子树的问题转换为区间问题
之后就是莫队的处理,只是一个神奇的算法,在我看来就是一种有技巧的暴力。另外还要注意对权值的离散化。PE orzz
  1 /******************************
  2 code by drizzle
  3 blog: www.cnblogs.com/hsd-/
  4 ^ ^    ^ ^
  5  O      O
  6 ******************************/
  7 #include<bits/stdc++.h>
  8 #include<map>
  9 #include<set>
 10 #include<cmath>
 11 #include<queue>
 12 #include<bitset>
 13 #include<math.h>
 14 #include<vector>
 15 #include<string>
 16 #include<stdio.h>
 17 #include<cstring>
 18 #include<iostream>
 19 #include<algorithm>
 20 #pragma comment(linker, "/STACK:102400000,102400000")
 21 using namespace std;
 22 #define  A first
 23 #define B second
 24 const int mod=1000000007;
 25 const int MOD1=1000000007;
 26 const int MOD2=1000000009;
 27 const double EPS=0.00000001;
 28 typedef __int64 ll;
 29 const ll MOD=1000000007;
 30 const int INF=1000000010;
 31 const ll MAX=1ll<<55;
 32 const double eps=1e-5;
 33 const double inf=~0u>>1;
 34 const double pi=acos(-1.0);
 35 typedef double db;
 36 typedef unsigned int uint;
 37 typedef unsigned long long ull;
 38 int T;
 39 int n,k,w[100005],v[100005],vv[100005],x,y,q;
 40 int in[100005],out[100005];
 41 int pre[100005];
 42 int pos[100005];
 43 int re[100005];
 44 int sum[100005];
 45 int dfn=0;
 46 int ans;int nedge=0;
 47 struct node
 48 {
 49     int pre,ed;
 50 }N[200005];
 51 struct query
 52 {
 53     int id;
 54     int l,r;
 55 }M[100005];
 56 void add(int st,int ed )
 57 {
 58     nedge++;
 59     N[nedge].ed=ed;
 60     N[nedge].pre=pre[st];
 61     pre[st]=nedge;
 62 }
 63 void getdfs(int now,int fa)
 64 {
 65     in[now]=++dfn;
 66     for(int i=pre[now];i;i=N[i].pre)
 67     {
 68         if(N[i].ed!=fa)
 69         {
 70             getdfs(N[i].ed,now);
 71         }
 72     }
 73     out[now]=dfn;
 74 }
 75 void init()
 76 {
 77     nedge=0;
 78     memset(pre,0,sizeof(pre));
 79     dfn=0;
 80     ans=0;
 81     memset(sum,0,sizeof(sum));
 82     memset(N,0,sizeof(N));
 83     memset(M,0,sizeof(M));
 84     memset(re,0,sizeof(re));
 85     memset(pos,0,sizeof(pos));
 86     memset(in,0,sizeof(in));
 87     memset(out,0,sizeof(out));
 88     memset(w,0,sizeof(w));
 89     memset(v,0,sizeof(v));
 90     memset(vv,0,sizeof(vv));
 91 }
 92 bool cmp(struct query aa,struct query bb)
 93 {
 94     if(pos[aa.id]<pos[bb.id])
 95         return true;
 96     if(pos[aa.id]==pos[bb.id])
 97     {
 98         if(aa.r<bb.r)
 99             return true;
100     }
101     return false;
102 }
103 void ad(int value)
104 {
105     if(sum[value]==k)
106         ans--;
107     sum[value]++;
108     if(sum[value]==k)
109        ans++;
110 }
111 void del(int value)
112 {
113     if(sum[value]==k)
114         ans--;
115     sum[value]--;
116     if(sum[value]==k)
117         ans++;
118 }
119 int main()
120 {
121     scanf("%d",&T);
122     for(int i=1;i<=T;i++)
123     {
124         init();
125         scanf("%d %d",&n,&k);
126         int block=sqrt(n);
127         for(int j=1;j<=n;j++){
128             scanf("%d",&w[j]);
129             v[j]=w[j];
130             }
131             sort(w+1,w+1+n);
132         for(int j=1;j<=n;j++){
133             v[j]=lower_bound(w+1,w+n+1,v[j])-w-1;
134             }
135         for(int j=1;j<n;j++){
136             scanf("%d %d",&x,&y);
137             add(x,y);add(y,x);
138         }
139         getdfs(1,1);
140         for(int j=1;j<=n;j++)
141             vv[in[j]]=v[j];// 将树上的权值 下放到区间当中
142         scanf("%d",&q);
143         int exm;
144         for(int j=1;j<=q;j++){
145             scanf("%d",&exm);
146             M[j].l=in[exm];
147             M[j].r=out[exm];
148             M[j].id=j;
149             pos[j]=(M[j].l)/block;//分块 处理的不是特别好
150         }
151         printf("Case #%d:
",i);
152         sort(M+1,M+1+q,cmp);
153         int l=1, r=0;//初始区间
154         ad(vv[++r]);
155         for(int j=1; j<=q; j++)
156         {
157             while(r<M[j].r) ad(vv[++r]);
158             while(r>M[j].r) del(vv[r--]);
159             while(l<M[j].l) del(vv[l++]);
160             while(l>M[j].l) ad(vv[--l]);
161             re[M[j].id]=ans;
162         }
163         for(int j=1;j<=q;j++)
164             printf("%d
",re[j]);
165         if(i!=T)
166             printf("
");
167     }
168     return 0;
169 }
原文地址:https://www.cnblogs.com/hsd-/p/5988287.html