一开始没思路 感觉像是一个树形dp 然而不会

然后看了一眼题解就明白了

一个点的子树 用dfs序表示肯定是一个连续的区间 并且由于有子树的距离限制 可以转化为一个深度的区间

于是每个点都会有一个在二维平面上的标号(x,y) == (编号,深度)

并且每次进行更新一个节点的子树的时候就可以得到一个x的区间和一个y的区间  (实际上这些x是独一无二的 y更像是一个限制的条件)

这样就可以转化成一个二维的平面 每次选择一个矩阵进行颜色的统一更新 询问单点的颜色 做一个延时标记

询问单点的时候可以每次找啊找直到找到这个点 也可以判断一下mark mark一定是最新的历史 如果这个点在这个区间里面并且这个区间有修改历史 那么ans就是mark

不过加了这个优化速度并没有提升多少

在这里kd-tree很像线段树 区别就是维度不同

找了一个小bug就直接a掉了 开心!

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<math.h>
#include<queue>
#include<string>
using namespace std;
#define L long long
const L INF = 999999999 ;
const L maxn = 100050 ;
const L mod = 1000000007;
/**
用dfs序设定每个点的子树的标号区间
存下每个点的deep
则每个点在二维平面的x为它的标号 y为它的深度 (如果仅要表示这个点主码x就可以了)
利用kdtree来进行区间修改单点查询
如果区间满足 Max[0] Min[0] 属于 x1 x2 && Max[1] Min[1] 属于 y11 y2 就直接修改这个区间的颜色 设置一个延时标记
x1 x2 == l[a] r[a] y11 y2 == deep[a] deep[a] + l
单点查询直接进行一个logn的查询
*/
L n , c , q ;
L deep[maxn] ;
vector<L >vec[maxn] ;
L l[maxn] , r[maxn] ;
L cnt ;
void dfs(L u , L dep) {
deep[u] = dep ;
l[u] = ++ cnt ;
for(L i = 0; i < vec[u].size(); i ++ ){
L v = vec[u][i] ;
dfs(v,dep + 1) ;
}
r[u] = cnt ;
}
L root , cmp_d ;
struct node {
L l , r ;
L d[2] , Max[2] , Min[2] ;
L c ;
L mark ;
}a[maxn];
bool cmp(node a,node b){return ((a.d[cmp_d] < b.d[cmp_d])||(a.d[cmp_d] == b.d[cmp_d] && a.d[!cmp_d] < b.d[!cmp_d])) ;} ;
void up(L p , L k ){
if(a[k].Max[0] > a[p].Max[0]) a[p].Max[0] = a[k].Max[0] ;
if(a[k].Max[1] > a[p].Max[1]) a[p].Max[1] = a[k].Max[1] ;
if(a[k].Min[0] < a[p].Min[0]) a[p].Min[0] = a[k].Min[0] ;
if(a[k].Min[1] < a[p].Min[1]) a[p].Min[1] = a[k].Min[1] ;
}
void down(L p) {
if(a[p].mark == 0)return ;
L newc = a[p].mark ;
a[p].mark = 0 ;
if(a[p].r) {
L rr = a[p].r ;
a[rr].c = newc ;
a[rr].mark = newc ;
}
if(a[p].l) {
L ll = a[p].l ;
a[ll].c = newc ;
a[ll].mark = newc ;
}
return ;
}
L build(L l, L r , L D) {
L mid = (l+r)/2 ;
cmp_d = D;
nth_element(a+1+l,a+1+mid,a+1+r,cmp) ;
a[mid].Max[0] = a[mid].Min[0] = a[mid].d[0] ;
a[mid].Max[1] = a[mid].Min[1] = a[mid].d[1] ;
a[mid].c = 1 ;
a[mid].mark = 0 ;
if(l != mid)a[mid].l = build(l,mid-1,D^1); else a[mid].l = 0;
if(r != mid)a[mid].r = build(mid+1,r,D^1); else a[mid].r = 0;
if(a[mid].l)up(mid,a[mid].l) ;
if(a[mid].r)up(mid,a[mid].r) ;
return mid ;
}
void upda(L p , L x1 , L y11 , L x2 , L y2 , L newc ) {
if(a[p].Max[0] < x1 || a[p].Min[0] > x2 || a[p].Max[1] < y11 || a[p].Min[1] > y2) {
return ;
}
if(a[p].Min[0] >= x1 && a[p].Max[0] <= x2 && a[p].Max[1] <= y2 && a[p].Min[1] >= y11) {
a[p].c = newc ;
a[p].mark = newc ;
return ;
}
down(p) ;
if(a[p].d[0] >= x1 && a[p].d[0] <= x2 && a[p].d[1] >= y11 && a[p].d[1] <= y2) {
a[p].c = newc ;
}
if(a[p].l) {
upda(a[p].l , x1, y11 , x2 , y2 , newc) ;
}
if(a[p].r) {
upda(a[p].r , x1, y11 , x2 , y2 , newc) ;
}
}
L ans ;
void ask(L p , L x, L y) {
if(a[p].d[0] == x && a[p].d[1] == y) {
ans = a[p].c ;
return ;
}
if(a[p].mark != 0) {
ans = a[p].mark ;
return ;
}
down(p) ;
if(a[p].l) {
L ll = a[p].l ;
if(x >= a[ll].Min[0] && x <= a[ll].Max[0] && y >= a[ll].Min[1] && y <= a[ll].Max[1]) {
ask(ll , x , y) ;
}
}
if(a[p].r) {
L ll = a[p].r ;
if(x >= a[ll].Min[0] && x <= a[ll].Max[0] && y >= a[ll].Min[1] && y <= a[ll].Max[1]) {
ask(ll , x , y) ;
}
}
}
int main(){
L t ;
scanf("%lld",&t);
while(t-- ){
scanf("%lld%lld%lld",&n,&c,&q) ;
for(L i = 1; i <= n ; i ++ )vec[i].clear() ;
for(L i = 2; i <= n ; i ++ ){
L fa ;
scanf("%lld",&fa) ;
vec[fa].push_back(i) ;
}
cnt = 0 ;
dfs(1,1) ;
for(L i = 1; i <= n; i ++ ){
a[i].l = a[i].r = 0;
a[i].d[0] = l[i] ;
a[i].d[1] = deep[i] ;
}
root = build(1,n,0) ;
L sum = 0;
for(L i = 1; i <= q; i ++ ){
L aa , ll , cc ;
scanf("%lld%lld%lld",&aa,&ll,&cc);
L x1 = l[aa] ;
L x2 = r[aa] ;
L y11 = deep[aa] ;
L y2 = deep[aa] + ll ;
if(cc != 0) {
upda(root , x1 , y11 , x2 , y2 , cc) ;
}
else {
ans = -1 ;
L x = l[aa] ;
L y = deep[aa] ;
ask(root, x , y) ;
sum += ans * i ;
sum %= mod ;
}
}
printf("%lld\n",sum) ;
}
}

  

BZOJ 4154 kd-tree dfs序 + 二维空间的区间(矩阵)更新单点查找的更多相关文章

  1. bzoj 2434 fail tree+dfs序

    首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tre ...

  2. POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和)

    POJ.3321 Apple Tree ( DFS序 线段树 单点更新 区间求和) 题意分析 卡卡屋前有一株苹果树,每年秋天,树上长了许多苹果.卡卡很喜欢苹果.树上有N个节点,卡卡给他们编号1到N,根 ...

  3. poj 3321 Apple Tree dfs序+线段树

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K       Description There is an apple tree outsid ...

  4. [poj3321]Apple Tree(dfs序+树状数组)

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 26762   Accepted: 7947 Descr ...

  5. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  6. Codeforces Round #200 (Div. 1)D. Water Tree dfs序

    D. Water Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/343/problem/ ...

  7. POJ3321Apple Tree Dfs序 树状数组

    出自——博客园-zhouzhendong ~去博客园看该题解~ 题目 POJ3321 Apple Tree 题意概括 有一颗01树,以结点1为树根,一开始所有的结点权值都是1,有两种操作: 1.改变其 ...

  8. [Split The Tree][dfs序+树状数组求区间数的种数]

    Split The Tree 时间限制: 1 Sec  内存限制: 128 MB提交: 46  解决: 11[提交] [状态] [讨论版] [命题人:admin] 题目描述 You are given ...

  9. Codeforces Round #381 (Div. 2) D. Alyona and a tree dfs序+树状数组

    D. Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

随机推荐

  1. 【BZOJ3124】[Sdoi2013]直径 树形DP(不用结论)

    [BZOJ3124][Sdoi2013]直径 Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节 ...

  2. 前端 为什么我选择用框架而不是Jquery

    对于很多习惯用Jquery的前端甚至后端,都很不解,为什么不用Jquery而是框架.觉得框架学起来麻烦,成本高,今天我以我浅薄的知识来总结一下为什么前台开发选择用框架: 前台开发,主要的性能是卡在回流 ...

  3. ubuntu14.0 hadoop2.4.0 64位基于jdk1.7搭建

    注意:hadoop有两种运行模式,安全模式和非安全模式.安装模式是以指定在健壮的,基于身份验证上运行的,本文无需运行在非安全模式下,可以直接使用root用户. 本文用户是基于root用户来运行的 一. ...

  4. python系列一:python3基础语法

    '''python保留字即关键字,我们不能把它们用作任何标识符名称.Python 的标准库提供了一个 keyword 模块,可以输出当前版本的所有关键字: '''>>> import ...

  5. ssm框架整合-过程总结(第三次周总结)

    本周主要是完成前端界面和后端的整合. 犹豫前后端的工作完成程度不一致,只实现了部分整合. 登录界面. 可能自己最近没有把重心放在短学期的项目上,导致我们工作的总体进度都要比别慢. 虽然我们只是三个人的 ...

  6. Hibernate 框架入门(一)

    1. SSH Web 层: Struts2 业务层: Spring 持久层: Hibernate 2. Hibernate 概述 概述 Hibernate 是一个对象关系映射框架(ORM 框架); 对 ...

  7. apply & call

    一.意义 function.apply(obj,args) obj代替function里this对象 args作为参数传给function 二.实例 1. obj代替function里this对象 f ...

  8. Python定时执行脚本

    最近测试hbase,老发现服务挂掉,自己不能及时发现,想了想,写了个脚本,让脚本每个小时执行一次,以便检测是否有服务挂掉,如果有服务挂掉,及时启动 import os import datetime ...

  9. 江卓尔与比特币增发,谣言or先知-千氪

    最近,很多圈内人都在讨论比特币是否应该增发,但等等,比特币真的会增发吗?到底是真有增发计划还是某些人别有用心地在散布谣言? 那么消息是从哪里出来的?北京时间 2 月 10 日晚,莱比特矿池创始人江卓尔 ...

  10. 李治军老师操作系统课程资源分享(视频+pdf)

    最近别人推荐,看看了哈工大的李治军老师主讲的操作系统,李治军老师通过linux0.11内核源码的讲解,学习了很多,更加形象了解了理论知识. 分享给大家,有pdf 链接:https://pan.baid ...