题意:N个节点的有根树,每个节点有一个weight。有Q个查询,问在以u为根的子树中,有恰好出现了K次的weight有多少种。
这是第一次写莫队算法,之前也只是偶有耳闻。
看了别人的代码打的,还是贴上来吧。
1 #pragma comment(linker, "/STACK:1000000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <fstream> 5 #include <algorithm> 6 #include <cmath> 7 #include <deque> 8 #include <vector> 9 #include <queue> 10 #include <string> 11 #include <cstring> 12 #include <map> 13 #include <stack> 14 #include <set> 15 #define LL long long 16 #define MAXN 100005 17 #define INF 0x3f3f3f3f 18 #define eps 1e-8 19 using namespace std; 20 int n, k, Q; 21 vector<int> p; 22 vector<int> G[MAXN]; 23 int a[MAXN], sum[MAXN]; 24 int L[MAXN], R[MAXN], res[MAXN]; 25 int t, ans; 26 struct Node 27 { 28 int left, right, id, pos; 29 Node(int left = 0, int right = 0, int id = 0, int pos = 0):left(left), right(right), id(id), pos(pos){}; 30 }m[MAXN]; 31 bool compare(Node a, Node b) 32 { 33 return (a.pos < b.pos ||(a.pos == b.pos && a.right < b.right)); 34 } 35 void dfs(int x, int father) 36 { 37 t++; 38 L[x] = t; 39 for(int i = 0; i < G[x].size(); i++){ 40 if(G[x][i] == father) continue; 41 dfs(G[x][i], x); 42 } 43 R[x] = t; 44 } 45 void work(int x, int v) 46 { 47 if(sum[x] == k){ 48 ans--; 49 } 50 sum[x] += v; 51 if(sum[x] == k){ 52 ans++; 53 } 54 } 55 56 int main() 57 { 58 //freopen("in.txt", "r", stdin); 59 int T; 60 scanf("%d", &T); 61 for(int cas = 1; cas <= T; cas++){ 62 scanf("%d%d", &n, &k); 63 p.clear(); 64 for(int i = 1; i <= n; i++){ 65 scanf("%d", &a[i]); 66 p.push_back(a[i]); 67 } 68 sort(p.begin(), p.end()); 69 for(int i = 1; i <= n; i++){ 70 a[i] = lower_bound(p.begin(), p.end(), a[i]) - p.begin(); 71 } 72 int x, y; 73 for(int i = 1; i <= n; i++){ 74 G[i].clear(); 75 } 76 for(int i = 1; i < n; i++){ 77 scanf("%d%d", &x, &y); 78 G[x].push_back(y); 79 G[y].push_back(x); 80 } 81 t = 0; 82 dfs(1, -1); 83 scanf("%d", &Q); 84 int u = sqrt(n); 85 for(int i = 1; i <= Q; i++){ 86 scanf("%d", &x); 87 m[i] = Node(L[x], R[x], i, L[x] / u); 88 } 89 sort(m + 1, m + Q + 1, compare); 90 memset(sum, 0, sizeof(sum)); 91 int left = 1, right = 1; 92 ans = 0; 93 work(a[right], 1); 94 for(int i = 1; i <= Q; i++){ 95 while(right < m[i].right){ 96 right++; 97 work(a[right], 1); 98 } 99 while(right > m[i].right){ 100 work(a[right--], -1); 101 } 102 while(left < m[i].left){ 103 work(a[left++], -1); 104 } 105 while(left > m[i].left){ 106 left--; 107 work(a[left], 1); 108 } 109 res[m[i].id] = ans; 110 } 111 printf("Case #%d: ", cas); 112 for(int i = 1; i <= Q; i++){ 113 printf("%d ", res[i]); 114 } 115 if(cas != T){ 116 printf(" "); 117 } 118 } 119 }