【bzoj4154】[Ipsc2015]Generating Synergy KD-tree

题目描述

给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色

输入

第一行一个数T,表示数据组数

接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数

接下来一行n-1个数描述2..n的父节点

接下来q行每行三个数a,l,c

若c为0,表示询问a的颜色

否则将距离a不超过l的a的子节点染成c

输出

设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+...+z_q模10^9+7

样例输入

1
4 3 7
1 2 2
3 0 0
2 1 3
3 0 0
1 0 2
2 0 0
4 1 1
4 0 0

样例输出

32



题解

KD-tree

“子树内”是dfs序限制,“距离不超过l”是深度限制。对满足两种限制的点的修改,可以将其看作平面上的点,修改相当于矩形修改,使用lazy标记+pushdown即可。

时间复杂度$O(n\sqrt n)$

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int head[N] , to[N] , next[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 , next[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 = next[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\n" , ans);
	}
	return 0;
}
时间: 2024-11-05 18:46:17

【bzoj4154】[Ipsc2015]Generating Synergy KD-tree的相关文章

【BZOJ4154】[Ipsc2015]Generating Synergy KDtree

[BZOJ4154][Ipsc2015]Generating Synergy Description 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色 Input 第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数 接下来一行n-1个数描述2..n的父节点 接下来q行每行三个数a,l,c 若c为0,表示询问a的颜色 否则将距离a不超过l的a的子节点染成c Output 设当前是第i个操作,y

【DataStructure】Description and Introduction of Tree

[Description] At ree is a nonlinear data structure that models a hierarchical organization. The characteristic eatures are that each element may have several successors (called its "children") and every element except one (called the "root&

【LeetCode】 Maximum Depth of Binary Tree

Maximum Depth of Binary Tree  Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node. 递归基础,不解释. class Solution { public: int getMax(TreeNode *root

【HDOJ】1325 Is It A Tree?

并查集.需要考虑入度. 1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXNUM 10005 5 6 int bin[MAXNUM]; 7 int degree[MAXNUM]; 8 int nums[MAXNUM]; 9 10 int find(int x) { 11 int r = x; 12 13 while (bin[r] != r) 14 r = bin[r]; 15 16 return r; 17 } 1

BZOJ 4154 [Ipsc2015]Generating Synergy(KD-Tree)

题目链接:BZOJ 4154 [Ipsc2015]Generating Synergy 题意: 给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色. 题解: 将dfs序看为x,dep看为y,那么就是一个在二维平面上的操作了. 由于这个平面范围比较大,二维线段树不好开,然后kd-tree搞搞. 1 #include<cstdio> 2 #include<algorithm> 3 #define F(i,a,b) for(int

【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. Input

【LeetCode】Minimum Depth of Binary Tree 二叉树的最小深度 java

[LeetCode]Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. 递归和非递归,此提比较简单.广度优先遍历即可.关键之处就在于如何保持访问深度. 下面是4种代码: 1

【BZOJ4530】大融合(Link-Cut Tree)

[BZOJ4530]大融合(Link-Cut Tree) 题面 讨厌权限题!!! Loj链接 题目描述 小强要在 N个孤立的星球上建立起一套通信系统.这套通信系统就是连接 N个点的一个树.这个树的边是一条一条添加上去的.在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量. 例如,在上图中,现在一共有五条边.其中,(3,8)这条边的负载是 6,因为有六条简单路径 2?3?8, 2?3?8?7, 3?8, 3?8?7, 4?3?8, 4?3?8?72-3-8,?2-3-8-

【BZOJ2843】极地旅行社(Link-Cut Tree)

[BZOJ2843]极地旅行社(Link-Cut Tree) 题面 BZOJ 题解 \(LCT\)模板题呀 没什么好说的了.. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<algorithm> #include<set> #include<map> #includ