zoukankan      html  css  js  c++  java
  • Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

    题目链接  Tree and Queries

    题目大意  给出一棵树和每个节点的颜色。每次询问$vj, kj$

    你需要回答在以$vj$为根的子树中满足条件的的颜色数目,

    条件:具有该颜色的节点数量至少为$kj$。

     

    (莫队居然可以过)

    首先转$DFS$序,这样就变成了区间查询。

    然后直接套用莫队,求出每次询问状态下的$t[],t[k]$表示当前区间内拥有$k$个节点的颜色数量。

    然后统计$t[k] + t[k + 1], ..., t[MAX]$即可,这个过程用树状数组维护。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)	for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)	for (int i(a); i >= (b); --i)
    
    const int N = 1e5 + 10;
    const int d = N + 10;
    
    int b[N], c[N * 3], f[N];
    int in[N], out[N];
    int a[N], belong[N];
    int n, m, ti = 0, bs = 0;
    int l, r;
    int ans[N];
    vector <int> v[N];
    
    struct node{
    	int v, k, id;
    	int l, r;
    	friend bool operator < (const node &a, const node &b){
    		return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];
    	}
    } q[N];
    
    inline void update(int x, int val){
    	for (; x <= (N * 3 - 10); x += x & -x) c[x] += val;
    
    }
    
    inline int query(int x){
    	if (x == 0) return c[x];
    	int ret = 0;
    	for (; x; x -= x & -x) ret += c[x];
    	return ret;
    }
    
    void dfs(int x, int fa){
    	in[x] = ++ti;
    	for (auto u : v[x]){
    		if (u == fa) continue;
    		dfs(u, x);
    	}
    	out[x] = ti;
    }
    
    
    int main(){
    
    	scanf("%d%d", &n, &m);
    	rep(i, 1, n) scanf("%d", a + i);
    	rep(i, 2, n){
    		int x, y;
    		scanf("%d%d", &x, &y);
    		v[x].push_back(y);
    		v[y].push_back(x);
    	}
    	
    	dfs(1, 0);
    
    	rep(i, 1, n) b[in[i]] = i;
    
    	rep(i, 1, m){
    		scanf("%d%d", &q[i].v, &q[i].k);
    		q[i].id = i;
    		q[i].l = in[q[i].v];
    		q[i].r = out[q[i].v];
    	}
    
    	bs = sqrt(n);
    	rep(i, 1, n) belong[i] = (i - 1) / bs + 1;
    	sort(q + 1, q + m + 1);
    
    
    
    	update(d, n);
    
    	l = 1, r = 0;
    
    	rep(i, 1, m){
    		while (l > q[i].l){
    			--l;
    			update(f[a[b[l]]] + d, -1);
    			++f[a[b[l]]];
    			update(f[a[b[l]]] + d,  1);	
    		}
    
    		while (l < q[i].l){
    			update(f[a[b[l]]] + d, -1);
    			--f[a[b[l]]];
    			update(f[a[b[l]]] + d, 1);
    			++l;
    		}
    
    		while (r < q[i].r){
    			++r;
    			update(f[a[b[r]]] + d, -1);
    			++f[a[b[r]]];
    			update(f[a[b[r]]] + d, 1);
    		}
    
    		while (r > q[i].r){
    			update(f[a[b[r]]] + d, -1);
    			--f[a[b[r]]];
    			update(f[a[b[r]]] + d, 1);
    			--r;
    		}
    		ans[q[i].id] = max(0, query(N * 3 - 10) - query(q[i].k - 1 + d));
    	}
    
    	rep(i, 1, m) printf("%d
    ", ans[i]);	
    	return 0;
    }
    
  • 相关阅读:
    人间故事馆话题:聊聊那些被骗经历,让其他人不再被骗
    路过的风景
    路过的风景
    上海最适合拍照的旅游地点
    Java EE (11)
    五、服务器端的局域网
    P1294 高手去散步 洛谷
    堆排序【模板】
    P3383 【模板】线性筛素数 洛谷
    P1516 青蛙的约会 洛谷
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7616157.html
Copyright © 2011-2022 走看看