CF1208H Red Blue Tree
CF1208H Red Blue Tree
原本应该放在这里但是这题过于毒瘤。。单独开了篇blog
首先考虑如果 $ k $ 无限小,那么显然整个树都是蓝色的。随着 $ k $ 逐渐增大,每个点都会有且仅有一次变色,我们考虑维护这个变色的时间 $ t $ 。如果每个点的变色时间都已经被算出来,那么我们可以轻易解决题目的查询操作和修改 $ k $ , 也就是说修改 $ k $ 本身就是个假操作。。只需要考虑的是修改单点颜色。
修改单点颜色,看起来就很 $ ddp $ 。树链剖分后,用$ f(x) = {a,b} $ 表示点 $ x $ 重儿子是 R
时的临界值是 $ a $ ,重儿子是 B
时临界值是 $ b $ 。
发现 $ f $ 这个东西是可以合并的!于是可以愉快地用线段树维护了呢~
但是除开重儿子怎么做呢,考虑每个点再开一个 BST
维护轻儿子当前的边界值。这个可以预处理的时候实现。同时我们意识到 $ \sum x $ ( $ x $ 是边界值 ) 是 $ n $ 级别的,所以我们可以对于每个点暴力出最开始的边界。具体的暴力方法是在build链剖后的线段树时先处理右子树,这样总可以保证处理到一个点时它的轻儿子都已经被插入到了它自己的平衡树,然后直接枚举边界值在平衡树判断就好了。
由于每次修改一个叶子,它的祖先的边界变化量是 $ O(1) $ 的,所以修改的复杂度是 $ O(log^2n) $
只是很难写
Orz LJZ_C 吊踩标算
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 200006
int n , k;
#define Update( cur ) if( cur -> left -> size ) cur -> size = cur -> left -> size + cur -> right -> size , cur -> value = cur -> right -> value
#define new_Node( s , v , a , b ) ( & ( * st[ cnt++ ] = Node( s , v , a , b ) ) )
#define Merge( a , b ) new_Node( a -> size + b -> size , b -> value , a , b )
#define ratio 4
namespace BST {
int cnt , s , a;
struct Node {
int size , value;
Node * left , * right;
Node( int s , int v , Node * a , Node * b ) : size( s ) , value( v ) , left( a ) , right( b ) {}
Node() {}
} * root[1000000] , * father , * st[1000000] , t[1000000] , * null;
inline void maintain( register Node * cur ) {
if( cur -> left -> size > cur -> right -> size * ratio ) cur -> right = Merge( cur -> left -> right , cur -> right ) , st[ --cnt ] = cur -> left , cur -> left = cur -> left -> left;
if( cur -> right -> size > cur -> left -> size * ratio ) cur -> left = Merge( cur -> left , cur -> right -> left ) , st[ --cnt ] = cur -> right , cur -> right = cur -> right -> right;
}
int find( int x , Node * cur ) {
if( cur -> size == 1 ) return cur -> value;
return x > cur -> left -> size ? find( x - cur -> left -> size , cur -> right ) : find( x , cur -> left );
}
int Rank( int x , Node * cur ) {
if( cur -> size == 1 ) return 1;
return x > cur -> left -> value ? Rank( x , cur -> right ) + cur -> left -> size : Rank( x , cur -> left );
}
void insert( int x , Node * cur ) {
if( cur -> size == 1 ) cur -> left = new_Node( 1 , min( cur -> value , x ) , null , null ) , cur -> right = new_Node( 1 , max( cur -> value , x ) , null , null );
else insert( x , x > cur -> left -> value ? cur -> right : cur -> left );
Update( cur );
maintain( cur );
}
void erase( int x , Node * cur ) {
if( cur -> size == 1 ) * father = cur == father -> left ? * father -> right : * father -> left;
else father = cur , erase( x , x > cur -> left -> value ? cur -> right : cur -> left );
Update( cur );
maintain( cur );
}
void init( ) {
null = new Node( 0 , 0 , 0 , 0 );
for( int i = 0 ; i < 1000000 ; ++ i ) st[i] = & t[i] , root[i] = new Node( 1 , 0x7f7f7f7f , null , null );
}
}
int head[MAXN] , nex[MAXN << 1] , to[MAXN << 1] , ecn = 0;
void ade( int u , int v ) {
nex[++ecn] = head[u] , to[ecn] = v , head[u] = ecn;
}
int fa[MAXN] , siz[MAXN] , hea[MAXN] , dep[MAXN] , top[MAXN] , tig[MAXN] , bac[MAXN] , en[MAXN] , clo;
void dfs( int u , int faa ) {
siz[u] = 1 , dep[u] = dep[faa] + 1;
for( int i = head[u] ; i ; i = nex[i] ) {
int v = to[i];
if( v == faa ) continue;
fa[v] = u;
dfs( v , u );
siz[u] += siz[v];
if( !hea[u] || siz[v] > siz[hea[u]] ) hea[u] = v;
}
}
void dfss( int u , int too ) {
tig[u] = ++ clo , bac[clo] = u , en[too] = u , top[u] = too;
if( !hea[u] ) return;
dfss( hea[u] , too );
for( int i = head[u] ; i ; i = nex[i] ) {
int v = to[i];
if( v == fa[u] || v == hea[u] ) continue;
dfss( v , v );
}
}
int col[MAXN];
struct node{
int l , r;
node( int L = 0 , int R = 0 ) : l(L) , r(R) { }
} T[MAXN << 2] , red( 0x3f3f3f3f , 0x3f3f3f3f ) , blu( -0x3f3f3f3f , -0x3f3f3f3f ) ;
int rec[MAXN];
// T[rt].l : if rt's heavy son is red , the value k to satisfy that this node is red
// T[rt].r : if rt's heavy son is blu , the value k to satisfy that this node is red
// b : 0 , r : 1
bool judge( int u , int k , int d ) {
// return we add d red nodes to its son if the node is red.
int B = BST :: Rank( k + 1 , BST :: root[u] ) - 1;
int R = BST :: Rank( 0x7f7f7f7f , BST :: root[u] ) - 1 - B;
return k >= R - B - d;
}
void update( int u , int& k , int d ) {
while( !judge( u , k , d ) ) ++ k;
while( judge( u , k - 1 , d ) ) -- k;
}
void work( int rt , int u ) {
if( col[u] == 0 ) {
T[rt] = red;
} else if( col[u] == 1 ) {
T[rt] = blu;
} else {
update( u , T[rt].l , 1 );
update( u , T[rt].r , -1 );
}
}
node merge( node a , node b ) {
node ret;
ret.l = min( max( b.l , a.l ) , a.r );
ret.r = min( max( b.r , a.l ) , a.r );
return ret;
}
void pushup( int rt ) {
T[rt] = merge( T[rt << 1] , T[rt << 1 | 1] );
}
node query( int rt , int l , int r , int L , int R ) {
if( l == L && r == R ) return T[rt];
int m = l + r >> 1;
if( R <= m ) return query( rt << 1 , l , m , L , R );
if( L > m ) return query( rt << 1 | 1 , m + 1 , r , L , R );
return merge( query( rt << 1 , l , m , L , m ) , query( rt << 1 | 1 , m + 1 , r , m + 1 , R ) );
}
void build( int rt , int l , int r ) {
if( l == r ) {
int u = bac[l];
work( rt , u );
if( u == top[u] && fa[u] )
BST :: insert( ( rec[u] = ( query( 1 , 1 , n , l , tig[en[u]] ) ).l ) , BST :: root[fa[u]] );
return;
}
int mid = l + r >> 1;
build( rt << 1 | 1 , mid + 1 , r ) , build( rt << 1 , l , mid );
pushup( rt );
}
void mdfy( int rt , int l , int r , int p ) {
if( l == r ) { work( rt , bac[l] ); return; }
int m = l + r >> 1;
if( p <= m ) mdfy( rt << 1 , l , m , p );
else mdfy( rt << 1 | 1 , m + 1 , r , p );
pushup( rt );
}
void modify( int x , int c ) {
col[x] = c;
while( x ) {
mdfy( 1 , 1 , n , tig[x] );
x = top[x];
if( fa[x] != 0 ) {
BST :: erase( rec[x] , BST :: root[fa[x]] );
BST :: insert( rec[x] = (query( 1 , 1 , n , tig[x] , tig[en[x]] ).l ) , BST :: root[fa[x]] );
}
x = fa[x];
}
}
int main() {
BST :: init( );
cin >> n >> k;
for( int i = 1 , u , v ; i < n ; ++ i ) {
scanf("%d%d",&u,&v);
ade( u , v ) , ade( v , u );
}
for( int i = 1 ; i <= n ; ++ i ) scanf("%d",&col[i]);
dfs( 1 , 1 );
dfss( 1 , 1 );
build( 1 , 1 , n );
int q , opt , v , c; cin >> q;
while( q-- ) {
scanf("%d",&opt);
if( opt == 1 ) {
scanf("%d",&v);
printf("%d\n",( query( 1 , 1 , n , tig[v] , tig[en[top[v]]] ).l ) <= -k);
} else if( opt == 2 ) {
scanf("%d%d",&v,&c);
modify( v , c );
} else {
scanf("%d",&c);
k = c;
}
}
}
CF1208H Red Blue Tree的更多相关文章
- CF1208 Red Blue Tree
题目链接 问题分析 这是蒟蒻第一道3500!不过话说luogu上两个题解的程序都是假的可还行(2019.11.1)-- 为了方便叙述,下面我们约定 : \([c]\) 的值为 \(1\) 当且仅当 \ ...
- BNUOJ 26229 Red/Blue Spanning Tree
Red/Blue Spanning Tree Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on HDU. ...
- Red–black tree ---reference wiki
source address:http://en.wikipedia.org/wiki/Red%E2%80%93black_tree A red–black tree is a type of sel ...
- [转载] 红黑树(Red Black Tree)- 对于 JDK TreeMap的实现
转载自http://blog.csdn.net/yangjun2/article/details/6542321 介绍另一种平衡二叉树:红黑树(Red Black Tree),红黑树由Rudolf B ...
- Red Black Tree 红黑树 AVL trees 2-3 trees 2-3-4 trees B-trees Red-black trees Balanced search tree 平衡搜索树
小结: 1.红黑树:典型的用途是实现关联数组 2.旋转 当我们在对红黑树进行插入和删除等操作时,对树做了修改,那么可能会违背红黑树的性质.为了保持红黑树的性质,我们可以通过对树进行旋转,即修改树中某些 ...
- 2018 ICPC青岛网络赛 B. Red Black Tree(倍增lca好题)
BaoBao has just found a rooted tree with n vertices and (n-1) weighted edges in his backyard. Among ...
- 计蒜客 Red Black Tree(树形DP)
You are given a rooted tree with n nodes. The nodes are numbered 1..n. The root is node 1, and m of ...
- Red Black Tree(红黑树)
(修改于 2018-05-06 15:53:22 还差删除维护操作.层序遍历没完成.维护操作没完成不想写层序遍历怎么办...) 今天下午完成了红黑树的插入的维护操作,但删除的维护操作还没有解决,删除的 ...
- ZOJ - 4048 Red Black Tree (LCA+贪心) The 2018 ACM-ICPC Asia Qingdao Regional Contest, Online
题意:一棵树上有m个红色结点,树的边有权值.q次查询,每次给出k个点,每次查询有且只有一次机会将n个点中任意一个点染红,令k个点中距离红色祖先距离最大的那个点的距离最小化.q次查询相互独立. 分析:数 ...
随机推荐
- Manjaro / ArchLinux 安装网易云音乐解决搜索不能输入中文方法
0. 安装网易云音乐 yay -S netease-cloud-music 1.先安装qcef这个软件包. sudo yay -S qcef 2.编辑/opt/netease/netease-clou ...
- Noip模拟10 2021.6.27
T1 入阵曲 好了,又一个考试败笔题. 也就是在那个时候,小 F 学会了矩阵乘法.让两个矩阵乘几次就能算出斐波那契数, 真是奇妙无比呢. 不过, 小 F 现在可不想手算矩阵乘法--他觉得好麻烦.取而代 ...
- 验证人员应该以何种角度阅读spec
转载:验证人员应该以何种角度阅读spec - 微波EDA网 (mweda.com) 在开发流程中,设计和验证人员关注的点肯定是不一样的,尤其在spec的理解上,验证人员往往需要有自己独立的理解.在拿到 ...
- 百亿级小文件存储,JuiceFS 在自动驾驶行业的最佳实践
自动驾驶是最近几年的热门领域,专注于自动驾驶技术的创业公司.新造车企业.传统车厂都在这个领域投入了大量的资源,推动着 L4.L5 级别自动驾驶体验能尽早进入我们的日常生活. 自动驾驶技术实现的核心环节 ...
- kail入侵win2003 sp2 中文版系统
攻击机:kail -- IP:192.168.74.132 目标靶机:win2003 sp2 中文版系统-- IP:192.168.74.128 一.扫描漏洞 1. 在kail中运行 namp 192 ...
- Kafka 消费迟滞监控工具 Burrow
Kafka 官方对于自身的 LAG 监控并没有太好的方法,虽然Kafka broker 自带有 kafka-topic.sh, kafka-consumer-groups.sh, kafka-cons ...
- docker 加入域名
先运行docker镜像 # 进入 docker 容器 mynginx 是容器名 docker exec -i -t mynginx /bin/bash #安装vim apt-get install v ...
- 这一篇 K8S(Kubernetes)集群部署 我觉得还可以!!!
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 国内安装K8S的四种途径 Kubernetes 的安装其实并不复杂,因为Kubernetes 属 ...
- Git使用教程之初级入门命令行(二)
一.Git 操作流程图 1.git --help 查看帮助 Administrator@PC-xiaobing MINGW64 /d/Git (master) $ git --help usage: ...
- 【Python+postman接口自动化测试】(4)HTTP 协议
前言 HTTP:超文本传输协议,是用于从WWW服务器传输超文本到本地浏览器的传输协议. HTTP协议是一种无状态协议,主要包含请求和相应两大部分. 请求(Request) get请求示范: GET h ...