zoukankan      html  css  js  c++  java
  • [HDU5709]Claris Loves Painting

    vjudge

    description

    给定一棵(n)点的树,每个节点上有一个颜色,每次询问一个点的子树中与这个点距离不超过(d)的点的颜色有多少种。强制在线。

    sol

    对每个点开两棵线段树,一棵以颜色为下标,表示每种颜色出现的最浅深度,一棵以深度为下标,表示以该深度为最浅深度的颜色有多少种。
    这两棵线段树都可以直接由儿子合并上来。
    在合并前一棵线段树的时候可能会导致第二棵线段树的修改(两个节点颜色相同,那就要删除深度更大的点的贡献),处理一下即可。
    复杂度(O(nlog n))

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 1e5+5;
    struct node{int ls,rs,w;}t[N*100];
    int n,m,col[N],nxt[N],head[N],rt1[N],rt2[N],tot,dep[N],ans;
    void build(int &x,int l,int r,int p,int v){
    	x=++tot;if (l==r) {t[x].w=v;return;}int mid=l+r>>1;
    	if (p<=mid) build(t[x].ls,l,mid,p,v);
    	else build(t[x].rs,mid+1,r,p,v);
    }
    void modify(int &x,int l,int r,int p,int v){
    	t[++tot]=t[x];t[x=tot].w+=v;if (l==r) return;int mid=l+r>>1;
    	if (p<=mid) modify(t[x].ls,l,mid,p,v);
    	else modify(t[x].rs,mid+1,r,p,v);
    }
    int merge_1(int x,int y,int l,int r,int u){
    	if (!x||!y) return x|y;int z=++tot,mid=l+r>>1;
    	if (l==r){
    		t[z].w=min(t[x].w,t[y].w);
    		modify(rt2[u],1,n,max(t[x].w,t[y].w),-1);
    	}
    	t[z].ls=merge_1(t[x].ls,t[y].ls,l,mid,u);
    	t[z].rs=merge_1(t[x].rs,t[y].rs,mid+1,r,u);
    	return z;
    }
    int merge_2(int x,int y){
    	if (!x||!y) return x|y;int z=++tot;t[z].w=t[x].w+t[y].w;
    	t[z].ls=merge_2(t[x].ls,t[y].ls);
    	t[z].rs=merge_2(t[x].rs,t[y].rs);
    	return z;
    }
    int query(int x,int l,int r,int ql,int qr){
    	if (l>=ql&&r<=qr) return t[x].w;int mid=l+r>>1,s=0;
    	if (ql<=mid) s+=query(t[x].ls,l,mid,ql,qr);
    	if (qr>mid) s+=query(t[x].rs,mid+1,r,ql,qr);
    	return s;
    }
    void dfs(int u){
    	build(rt1[u],1,n,col[u],dep[u]);modify(rt2[u],1,n,dep[u],1);
    	for (int v=head[u];v;v=nxt[v]){
    		dep[v]=dep[u]+1,dfs(v);
    		rt1[u]=merge_1(rt1[u],rt1[v],1,n,u);
    		rt2[u]=merge_2(rt2[u],rt2[v]);
    	}
    }
    int main(){
    	int Case=gi();while (Case--){
    		n=gi();m=gi();ans=0;
    		for (int i=1;i<=tot;++i) t[i]=(node){0,0,0};tot=0;
    		for (int i=1;i<=n;++i) col[i]=gi(),head[i]=rt1[i]=rt2[i]=0;
    		for (int i=2,f;i<=n;++i) nxt[i]=head[f=gi()],head[f]=i;
    		dep[1]=1;dfs(1);
    		while (m--){
    			int x=gi()^ans,d=gi()^ans;
    			printf("%d
    ",ans=query(rt2[x],1,n,dep[x],dep[x]+d));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Java事务
    Mybatis二级缓存问题
    183.面试题 17.14. 最小K个数(快速排序)
    182. 跟着三叶学最短路径问题(存图方式)
    181. 差分数组学习
    AI大视觉(二十) | 小目标检测的tricks汇总
    CentOS7 上安装 mysql-5.7.26
    如何欺骗 Go Mod?
    .netcore docker常用命令-持续补充
    转载:登录后,用户配置被修改的处理方法
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9398700.html
Copyright © 2011-2022 走看看