zoukankan      html  css  js  c++  java
  • [bzoj4154][Ipsc2015]Generating Synergy_KD-Tree_dfs序

    Generating Synergy bzoj-4154 Ipsc-2015

    题目大意:给定一棵n个节点树,m个操作,支持:将一个点周围所有距该点距离不超过l的子结点的颜色改成另一种颜色;查询单点颜色。每个点的颜色开始都是1。

    注释:$1le n,mle 10^5$


    想法:这就是一个典型的不是KD-Tree裸题,我们需要将它转化成点。

    首先,我们先拉出整棵树的dfs序。

    每个节点,我们设横坐标就是dfs序上的下标,纵坐标就是深度。我们发现,一个点的子树是一段连续的区间,然后当深度确定是,我们发现这就是矩阵赋值,加上pushdown操作即可。

    单点查询遍历即可。不要忘记query的时候也要pushdown

    另外没有插入操作,就不用重构了。

    最后,附上丑陋的代码... ...

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 100010
    using namespace std;
    int head[N],to[N],nxt[N],cnt,deep[N],pos[N],last[N],tot,d,root;
    struct data
    {
    	int p[2],mx[2],mn[2],c[2],w,tag;
    	bool operator <(const data &a) const
    	{
    		return p[d]==a.p[d]?p[d^1]<a.p[d^1]:p[d]<a.p[d];
    	}
    }a[N];
    inline void add(int x,int y)
    {
    	to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
    }
    void dfs(int x)
    {
    	int i;
    	pos[x]=++tot,a[x].p[0]=pos[x],a[x].p[1]=deep[x];
    	for(i=head[x];i;i=nxt[i])
    		deep[to[i]]=deep[x]+1,dfs(to[i]);
    	last[x]=tot;
    }
    inline void pushup(int x)
    {
    	int l=a[x].c[0],r=a[x].c[1];
    	a[x].mx[0]=max(a[x].p[0],max(a[l].mx[0],a[r].mx[0]));
    	a[x].mx[1]=max(a[x].p[1],max(a[l].mx[1],a[r].mx[1]));
    	a[x].mn[0]=min(a[x].p[0],min(a[l].mn[0],a[r].mn[0]));
    	a[x].mn[1]=min(a[x].p[1],min(a[l].mn[1],a[r].mn[1]));
    }
    int build(int l,int r,int now)
    {
    	if(l>r) return 0;
    	int mid=(l+r)>>1;
    	d=now,nth_element(a+l,a+mid,a+r+1);
    	a[mid].w=1,a[mid].tag=0;
    	a[mid].c[0]=build(l,mid-1,now^1);
    	a[mid].c[1]=build(mid+1,r,now^1);
    	pushup(mid);
    	return mid;
    }
    inline void pushdown(int x)
    {
    	if(a[x].tag)
    	{
    		int l=a[x].c[0],r=a[x].c[1];
    		a[l].w=a[l].tag=a[r].w=a[r].tag=a[x].tag;
    		a[x].tag=0;
    	}
    }
    void update(int bx,int ex,int by,int ey,int v,int x)
    {
    	if(!x||a[x].mx[0]<bx||a[x].mn[0]>ex||a[x].mx[1]<by||a[x].mn[1]>ey)return;
    	if(a[x].mn[0]>=bx&&a[x].mx[0]<=ex&&a[x].mn[1]>=by&&a[x].mx[1]<=ey)
    	{
    		a[x].w=a[x].tag=v;
    		return;
    	}
    	pushdown(x);
    	if(a[x].p[0]>=bx&&a[x].p[0]<=ex&&a[x].p[1]>=by&&a[x].p[1]<=ey)a[x].w=v;
    	update(bx,ex,by,ey,v,a[x].c[0]),update(bx,ex,by,ey,v,a[x].c[1]);
    }
    int query(int px,int py,int x)
    {
    	d^=1;
    	if(a[x].p[0]==px&&a[x].p[1]==py) return a[x].w;
    	pushdown(x);
    	if(d)
    	{
    		if(py<a[x].p[1]||(py==a[x].p[1]&&px<a[x].p[0])) return query(px,py,a[x].c[0]);
    		else return query(px,py,a[x].c[1]);
    	}
    	else
    	{
    		if(px<a[x].p[0]||(px==a[x].p[0]&&py<a[x].p[1])) return query(px,py,a[x].c[0]);
    		else return query(px,py,a[x].c[1]);
    	}
    }
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		memset(head,0,sizeof(head)),cnt=1;
    		a[0].mx[0]=a[0].mx[1]=-1<<30,a[0].mn[0]=a[0].mn[1]=1<<30;
    		int n,m,i,x,y,z,ans=0;
    		scanf("%d%*d%d",&n,&m);
    		for(i=2;i<=n;i++) scanf("%d",&x),add(x,i);
    		dfs(1);
    		root=build(1,n,0);
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d%d",&x,&y,&z);
    			if(z) update(pos[x],last[x],deep[x],deep[x]+y,z,root);
    			else d=1,ans=(ans+(long long)query(pos[x],deep[x],root)*i)%1000000007;
    		}
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    

    小结:KD-Tree这种题还是挺好玩的..

  • 相关阅读:
    [Cocos2d-x]布局与定位
    [Cocos2d-x]创建项目
    nylg-154-king 选 太子
    nylg-153-king VS king
    hdoj-2053-Switch Game
    hdoj-2052-Picture
    hdoj-2051-Bitset
    hdoj-2050-折线分割平面
    大一c语言课程设计-学籍管理系统
    hdoj-2049-不容易系列之(4)——考新郎
  • 原文地址:https://www.cnblogs.com/ShuraK/p/9393184.html
Copyright © 2011-2022 走看看