[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)\) 个结点的一棵树, ...
随机推荐
- 算数组的长度cpp
今天被自己整傻了.... cpp int 型的数组就别想用strlen来求长度了,会报错的. (当然java 里直接用length就可以了...) 所以我建议用vector!!!!!!
- PHP date_add() 函数
------------恢复内容开始------------ 实例 添加 40 天到 2013 年 3 月 15 日: <?php$date=date_create("2013-03- ...
- PHP fflush() 函数
定义和用法 fflush() 函数向打开的文件写入所有的缓冲输出. 如果成功则返回 TRUE,如果失败则返回 FALSE. 语法 fflush(file) 参数 描述 file 必需.规定要检查的打开 ...
- PHP is_finite() 函数
实例 判断一个值是否为有限值: <?phpecho is_finite(2) . "<br>";echo is_finite(log(0)) . "&l ...
- PHP md5_file() 函数
实例 计算文本文件 "test.txt" 的 MD5 散列: <?php高佣联盟 www.cgewang.com$filename = "test.txt" ...
- setOff与scrollTop区别
1.offsetTop : 当前对象到其上级层顶部的距离. 不能对其进行赋值.设置对象到页面顶部的距离请用style.top属性. 2.offsetLeft : 当前对象到其上级层左边的 ...
- kafka的学习1
1.Kafka是什么? Apache Kafka 是一款开源的分布式消息引擎系统.倘若“消息引擎系统”这个词对你来说有点陌生的话,那么“消息队列”“消息中间件”的提法想必你一定是有所耳闻的.不过说实话 ...
- 比原Bapp红包应用
喜迎国庆期间,比原链在自己的移动端钱包Bycoin(下载地址)和google插件钱byone中推出了红包应用,在国庆期间深受大家好评. 那我们今天就来大概介绍一下比原红包,以及基于比原链开发dapp应 ...
- 2020-06-25:B+树和B树有什么区别?
福哥答案2020-06-25: B树:1.叶子节点和非叶子节点都存数据.2.数据无链指针.B+树:1.只有叶子节点存数据.2.数据有链指针.B树优势:1.靠近根节点的数据,访问速度快.B+树优势:1. ...
- LeetCode 392. Is Subsequence 详解
题目详情 给定字符串 s 和 t ,判断 s 是否为 t 的子序列. 你可以认为 s 和 t 中仅包含英文小写字母.字符串 t 可能会很长(长度 ~= 500,000),而 s 是个短字符串(长度 & ...