zoukankan      html  css  js  c++  java
  • 375D.Tree and Queries(树上启发式合并+离线)

    给出一个n个点的树。

    每次询问点x的子树内出现次数为y的颜色至少有多少种。

    题解:

    先将询问离线。

    用f数组记录每种颜色在当前子树内的出现次数情况

    用cnt数组记录当前子树内出现次数大于等于i的不同颜色数量

    当前节点的f和cnt来源于重儿子。

    然后更新f的状态时,cnt[f[i]]++即可。

    然后遍历与当前节点有关的每个询问,依次输出cnt[f[i]]即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    int n,m;
    int c[maxn];
    vector<int> g[maxn];
    int tot;
    int L[maxn];
    int R[maxn];
    int id[maxn];
    int son[maxn];
    int f[maxn];
    int ans[maxn];
    int size[maxn];
    int cnt[maxn];
    int dep[maxn];
    vector<pair<int,int> > q[maxn];
    //first表示询问的编号,second表示询问的k 
    void dfs1 (int x,int pre) {
    	dep[x]=dep[pre]+1;
    	size[x]=1;
    	L[x]=++tot;
    	id[tot]=x;
    	for (int y:g[x]) {
    		if (y==pre) continue;
    		dfs1(y,x);
    		size[x]+=size[y];
    		if (size[son[x]]<size[y]) son[x]=y;
    	}
    	R[x]=tot;
    } 
    void cal (int x,int pre) {
    	f[c[x]]++;
    	cnt[f[c[x]]]++;
    	for (int y:g[x]) {
    		if (y==son[x]||y==pre) continue;
    		for (int j=L[y];j<=R[y];j++) {
    			int z=id[j];
    			f[c[z]]++;
    			cnt[f[c[z]]]++;
    		}
    	}
    	for (pair<int,int> y:q[x]) {
    		ans[y.second]=cnt[y.first];
    	}
    }
    void dfs2 (int x,int pre,int kp) {
    	for (int y:g[x]) {
    		if (y==son[x]) continue;
    		if (y==pre) continue;
    		dfs2(y,x,0);
    	}
    	if (son[x]) {
    		dfs2(son[x],x,1);
    	}
    	cal(x,pre);
    	if (!kp) {
    		int Max=0;
    		for (int i=L[x];i<=R[x];i++) {
    			Max=max(Max,f[c[id[i]]]);
    			f[c[id[i]]]=0;
    		}
    		for (int i=0;i<=Max;i++) cnt[i]=0;
    	}
    }
    int main () {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) scanf("%d",c+i);
    	for (int i=1;i<n;i++) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		g[x].push_back(y);
    		g[y].push_back(x);
    	}
    	for (int i=1;i<=m;i++) {
    		int x,y;
    		scanf("%d%d",&x,&y);
    		q[x].push_back(make_pair(y,i));
    	}
    	dfs1(1,0);
    	dfs2(1,0,1);
    	for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
  • 相关阅读:
    Microsoft Office MIME Types
    启动mongodb
    学习Hbase API的一个视频
    报错:Hive Runtime Error while processing row
    821. Shortest Distance to a Character
    1171. Remove Zero Sum Consecutive Nodes from Linked List
    190. Reverse Bits
    Rust--如何实现内存安全的?
    Rust -- as_ref与borrow的区别
    653. Two Sum IV
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14608713.html
Copyright © 2011-2022 走看看