[HDU6793] Tokitsukaze and Colorful Tree
题目
又是一个条历新年,窗前的灼之花又盛开了。
时隔多年,现在只有这一棵树上盛开着残存的 \(n\) 朵灼之花了。
尽管如此,这些灼之 花仍散发出不同色彩的微弱的光芒。 灼之花的生命极为短暂,但它的花色与光亮瞬息万变。
作为条条的粉丝,Little Q 细致 地记录了最初每朵灼之花的花色 \(c_i\) 和光亮 \(l_i\) ,以及接下来的 \(m\) 秒中灼之花的变化,第 \(i\) 秒会发生下面两种变化之一:
- " \(1\ t_i\ c_i'\) " 第 \(t_i\) 朵灼之花的颜色变为 \(c_i'\) ;
- " \(2\ t_i\ l_i'\) " 第 \(t_i\) 朵灼之花的光亮变为 \(l_i'\) ;
灼之花一齐盛开的景象令人过目难忘,其美丽值为每对生长在不同枝杈的相同颜色的灼之花的光亮值的异或和:
\]
数据范围: \(1\le c_i,c_i'\le n,m\le 10^6, 0\le l_i,l_i'\le 2^{20}\) 。
原题:[HDU6793]Tokitsukaze and Colorful Tree 。
分析
首先需要一些基础的分析。
第一步,异或首先按位进行拆分。
第二步,显然,我们总可以将变化拆分成向某个颜色的集合中插入或者删除一个点。
第三步,接着我们需要考虑动态地维护插入一个点或删除一个点之后,同种颜色中异或为 1 的符合条件的点对数量。
我们只需要考虑与变化的点有关的点对。异或为 1 可以简单地分类讨论,我们需要考虑 \(\operatorname{LCA}\) 的限制。
不难发现,我们只需要减去下列不合法的点即可:
对应点在根到当前点的路径上。
对应点在当前点的子树内。
第一个部分可以考虑维护贡献,等价于每次修改子树,也就是 DFS 序上的一段区间,区间加 - 单点查。
第二个部分可以考虑统计贡献,直接在 DFS 序上面维护,单点加 - 区间查。
如果需要在线算法,就可以用维护 \(n\) 个 \(splay\) ,分别维护 \(n\) 种颜色的点的部分 DFS 序。
如果需要离线算法,就可以直接使用整棵树的 DFS 序,然后用 4 个 BIT 分别维护。
时间复杂度 \(O(m\log_2n\log_2l)\) 。
本题的一些有价值的点:
- 对于变化操作的拆分,转化为简单的情形。
- 统计贡献与维护贡献两种思想。
代码
由于这是模拟赛里面的题目,所以没有处理多组数据。
#include <cstdio>
#include <vector>
using namespace std;
typedef long long LL;
#define int LL
const int MAXN = 1e5 + 5, MAXS = MAXN << 1;
template<typename _T>
void read( _T &x )
{
x = 0;char s = getchar();int f = 1;
while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
if( 9 < x ){ write( x / 10 ); }
putchar( x % 10 + '0' );
}
struct edge
{
int to, nxt;
}Graph[MAXN << 1];
struct oper
{
int typ, pos, nVal, sta;
oper() { typ = pos = nVal = sta = 0; }
oper( int a, int b, int c, int d ) { typ = a, pos = b, nVal = c, sta = d; }
};
//1->add, 0->delete
vector<oper> O[MAXN];
LL ans[MAXN];
int dif[MAXN];
int C[MAXN], L[MAXN];
int head[MAXN], DFN[MAXN], siz[MAXN];
int N, M, cnt, ID, D;
int tot[2]; LL all;
struct BinIndTree
{
int BIT[MAXN];
void up( int &x ) { x += ( x & ( -x ) ); }
void down( int &x ) { x -= ( x & ( -x ) ); }
void update( int x, const int v ) { for( ; x <= N ; up( x ) ) BIT[x] += v; }
int getSum( int x ) { int ret = 0; for( ; x ; down( x ) ) ret += BIT[x]; return ret; }
int query( const int l, const int r ) { return getSum( r ) - getSum( l - 1 ); }
};
struct RtoU : BinIndTree
{
int Q( const int x ) { return getSum( DFN[x] ); }
void upt( const int x, const int v ) { update( DFN[x], v ), update( DFN[x] + siz[x], -v ); };
}R[2];
struct SubT : BinIndTree
{
int Q( const int x ) { return query( DFN[x], DFN[x] + siz[x] - 1 ); }
void upt( const int x, const int v ) { update( DFN[x], v ); }
}S[2];
void addEdge( const int from, const int to )
{
Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
head[from] = cnt;
}
void init( const int u, const int fa )
{
DFN[u] = ++ ID, siz[u] = 1;
for( int i = head[u], v ; i ; i = Graph[i].nxt )
if( ( v = Graph[i].to ) ^ fa )
init( v, u ), siz[u] += siz[v];
}
int get( const int u, const int t )
{
int a = R[t].Q( u ), b = S[t].Q( u );
return a + b;
}
void launch( oper cur )
{
int u = cur.pos, delt = cur.nVal >> D & 1, val;
if( cur.typ )
{
val = tot[delt ^ 1] - get( u, delt ^ 1 );
R[delt].upt( u, 1 ), S[delt].upt( u, 1 ), tot[delt] ++;
}
else
{
R[delt].upt( u, -1 ), S[delt].upt( u, -1 ), tot[delt] --;
val = - tot[delt ^ 1] + get( u, delt ^ 1 );
}
all += val;
}
signed main()
{
read( N );
for( int i = 1 ; i <= N ; i ++ ) read( C[i] );
for( int i = 1 ; i <= N ; i ++ ) read( L[i] );
for( int i = 1, a, b ; i < N ; i ++ ) read( a ), read( b ), addEdge( a, b ), addEdge( b, a );
init( 1, 0 ), read( M );
for( int i = 1 ; i <= N ; i ++ ) O[C[i]].push_back( oper( 1, i, L[i], 0 ) );
for( int i = 1 ; i <= M ; i ++ )
{
int opt, x, y;
read( opt ), read( x ), read( y );
if( opt == 1 )
O[C[x]].push_back( oper( 0, x, L[x], i ) ),
O[C[x] = y].push_back( oper( 1, x, L[x], i ) );
else
O[C[x]].push_back( oper( 0, x, L[x], i ) ),
O[C[x]].push_back( oper( 1, x, L[x] = y, i ) );
}
for( int i = 1 ; i <= N ; i ++ ) O[C[i]].push_back( oper( 0, i, L[i], M + 1 ) );
for( D = 0 ; D < 20 ; D ++ )
{
for( int i = 0 ; i <= M ; i ++ ) dif[i] = 0;
for( int col = 1 ; col <= N ; col ++ )
{
tot[0] = tot[1] = 0;
int lim = ( int ) O[col].size(), ed;
for( int k = 0, r = 0 ; k < lim ; )
{
for( r = k ; r < lim && O[col][r].sta == O[col][k].sta ; r ++ );
ed = r == lim ? M + 1 : O[col][r].sta;
for( ; k < r ; k ++ ) launch( O[col][k] );
dif[O[col][k - 1].sta] += all, dif[ed] -= all;
}
}
for( int i = 1 ; i <= M ; i ++ ) dif[i] += dif[i - 1];
for( int i = 0 ; i <= M ; i ++ ) ans[i] += ( 1ll << D ) * dif[i];
}
for( int i = 0 ; i <= M ; i ++ ) write( ans[i] ), putchar( '\n' );
return 0;
}
[HDU6793] Tokitsukaze and Colorful Tree的更多相关文章
- 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】
Colorful Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)T ...
- hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。
/** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...
- AtCoder Beginner Contest 133 F Colorful Tree
Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...
- HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1
/* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...
- Colorful tree
cnbb 我被数组清零卡了一天.. 子树改色询问子树颜色数.. 先考虑颜色为x的节点对祖先答案的贡献,那么我们考虑把所有这些节点都搞出来,按dfs序排序,然后考虑每个节点a掌管的祖先是它和按dfs序的 ...
- 2017ACM暑期多校联合训练 - Team 1 1003 HDU 6035 Colorful Tree (dfs)
题目链接 Problem Description There is a tree with n nodes, each of which has a type of color represented ...
- HDU-6035:Colorful Tree(虚树+DP)
这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...
- ABC133F - Colorful Tree
ABC133FColorful Tree 题意 给定一颗边有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离. 数据都是1e5量级的. 思路 我自己一开始用树链 ...
- HDU6035 Colorful Tree
题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...
随机推荐
- 巩固复习(Django最基础的部分_具体查看官方文档)
Django学习路1 1.脚本不能随便运行,没准 linux 运行完就上不去了 2.pip 在 linux 上 写 pip3 同理 python 写为 python3 3.在 pycharm 上安装库 ...
- 11-19 configparser模块
该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值). 创建文件 import configparser config = ...
- Codeforces Round #654 (Div. 2) A~E 题解
LINK:CF R 654 div2 前言:F题是一个线段树分类讨论的题目 比赛的时候没看 赛后感觉没什么意思 所以咕掉了. 记事:第一次笼统的写一场比赛的题目 可能是我这场比赛打的太差了 题目不难 ...
- Java不会被淘汰的12个原因
如今,面对曾经在程序员中被各种新技术掩盖直至堙灭的技术值得怀念.犹如COBOL这当年被老程序员们尊为神器的语言如今也基本没有价值.而Java作为现代程序员的中坚力量在这点上或许会成为下一个COBOL. ...
- Springboot+Mybatis+Clickhouse+jsp 搭建单体应用项目(三)(添加增删改查)
一.添加增加接口 @ApiResponses(value = { @ApiResponse(code = 200, message = "接口返回成功状态"), @ApiRespo ...
- 使用QT实现一个简单的登陆对话框(纯代码实现C++)
使用QT实现一个简单的登陆对话框(纯代码实现C++) 效果展示 使用的QT控件 控件 描述 QLable 标签 QLineEdit 行文本框 QPushButton 按扭 QHBoxLayout 水平 ...
- DevOps让金融业数字化转型更敏捷 | 分享实录
以下为博云近期在活动中分享的关于<如何通过 DevOps 让数字化转型变得更加敏捷>的主题演讲实录. 01 金融科技进入VUCA时代 大家好,今天分享的题目是<如何通过 DevOps ...
- Coders' Legacy 2020 题解
目录 Chef vs Doof Doof on Cartesian Doof fires Brackets Jeremy gets a gift Unique Substring Perry lear ...
- pandas | 详解DataFrame中的apply与applymap方法
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是pandas数据处理专题的第5篇文章,我们来聊聊pandas的一些高级运算. 在上一篇文章当中,我们介绍了panads的一些计算方法, ...
- C#LeetCode刷题之#852-山脉数组的峰顶索引(Peak Index in a Mountain Array)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4003 访问. 我们把符合下列属性的数组 A 称作山脉: A.le ...