1. 程式人生 > >HDU4358【離散化+DFS序+莫隊演算法】

HDU4358【離散化+DFS序+莫隊演算法】

思路:
這個DFS序還是蠻有意思的~然後就可以把以u為根的樹的狀態直接轉化到區間(一維陣列)上,而且陣列是不大的。
然後就變成了區間處理,套一下莫隊就好了。
Code:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

#define mem(a, b) memset(a, b, sizeof(a))
const int Maxn = 1e5 + 10;
struct Edge{int v, nex;}edge[Maxn<<1];
int head[Maxn], tol;
void
init(){tol = 0,mem(head, -1);} void addedge(int u, int v){ edge[tol] = (Edge){v, head[u]}, head[u] = tol++; edge[tol] = (Edge){u, head[v]}, head[v] = tol++; } int w[Maxn], _time, val[Maxn], n, k, q, a[Maxn]; int Left[Maxn], Right[Maxn]; vector<int>xs; struct asd{ int id; int Left, Right; }node[Maxn]; int
res[Maxn], ans, sum[Maxn]; int pos[Maxn]; bool cmp(asd x,asd y) { if(pos[x.Left] == pos[y.Left]) return x.Right<y.Right; return pos[x.Left]<pos[y.Left]; } void DFS(int u, int fa){ int v; Left[u] = ++_time, w[_time] = a[u]; for(int i=head[u]; ~i;i = edge[i].nex){ v = edge[i].v; if
(v == fa) continue; DFS(v, u); } Right[u] = _time; } void ADD(int ww){ if(sum[ww] == k) ans--; sum[ww]++; if(sum[ww] == k) ans++; } void DEL(int ww){ if(sum[ww] == k) ans--; sum[ww]--; if(sum[ww] == k) ans++; } void solve(){ ans=0; mem(sum, 0); sort(node+1, node+1+q, cmp); for(int i=node[1].Left;i<=node[1].Right;i++){ ADD(w[i]); } res[node[1].id]=ans; int L=node[1].Left,R=node[1].Right; for(int i=2; i<=q; i++){ while(R<node[i].Right){ R++; ADD(w[R]); } while(R>node[i].Right){ DEL(w[R]); R--; } while(L<node[i].Left){ DEL(w[L]); L++; } while(L>node[i].Left){ L--; ADD(w[L]); } res[node[i].id]=ans; } for(int i=1;i<=q;i++) printf("%d\n", res[i]); } int main() { int T, u, v, L, R; scanf("%d", &T); for(int cas = 1; cas <= T; cas++){ scanf("%d%d",&n, &k); xs.clear(); int block=(int)sqrt(n); for(int i=1;i<=n;i++){ scanf("%d", &a[i]); xs.push_back(a[i]); pos[i]=(i-1)/block+1; } sort(xs.begin(), xs.end()); xs.erase(unique(xs.begin(), xs.end()), xs.end()); for(int i=1;i<=n;++i) a[i] = lower_bound(xs.begin(), xs.end(), a[i]) - xs.begin() + 1; init(); for(int i=1;i<n;i++){ scanf("%d%d", &u, &v); addedge(u, v); } _time = 0; DFS(1, -1); scanf("%d", &q); for(int i=1;i<=q;i++){ scanf("%d", &u); node[i].id = i; node[i].Left = Left[u], node[i].Right = Right[u]; } printf("Case #%d:\n", cas); solve(); if(cas != T) puts(""); } return 0; }