[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)\) 个结点的一棵树, ...
随机推荐
- scrapyd 部署
步骤 1 pip install scrapyd pip install scrapy-client 步骤 2 修改 scrapy.cfg [deploy:targetName]url = http: ...
- 总结HashMap实现原理分析
一.底层数据结构在JDK1.6,JDK1.7中,HashMap采用位桶+链表实现,即使用链表处理冲突,同一hash值的键值对会被放在同一个位桶里,当桶中元素较多时,通过key值查找的效率较低. 而JD ...
- 前端网(http://www.qdfuns.com/)不能访问了
前端网(http://www.qdfuns.com/)不能访问了 之前写的一些知识点也找不到了,有点难受.... 这说明知识点还是放在本地电脑稳一点,多备份,云端时刻在变化... 希望博客园别也用着用 ...
- PHP xml_get_current_column_number() 函数
定义和用法 xml_get_current_column_number() 函数获取 XML 解析器的当前列号. 如果成功,该函数则返回当前列号.如果失败,则返回 FALSE.高佣联盟 www.cge ...
- SpringClould进行Devtools热部署
当我们在使用SpringCloud搭建项目的时候,会有多个项目,每次修改东西的时候,都需要重新启动项目,这样的操作就比较繁琐. 为了提高工作的效率,避免每次频繁的重启项目,在子类pom文件中,我们可以 ...
- bzoj 3782 上学路线 卢卡斯定理 容斥 中国剩余定理 dp
LINK:上学路线 从(0,0)走到(n,m)每次只能向上或者向右走 有K个点不能走求方案数,对P取模. \(1\leq N,M\leq 10^10 0\leq T\leq 200\) p=10000 ...
- JavaWeb项目的部署以及远程调试
Linux环境下软件的安装 Linux环境下的程序的安装.更新.卸载和查看. rpm 命令:相当于windows程序的添加/卸载程序,进程程序的安装,查看,卸载. 本地程序安装:rpm -ivh 程序 ...
- 在Ubuntu18.04系统里面安装VMware tools遇到的问题 以及解决办法
问题1:Ubuntu18.4下安装VMware Tools 一直提示 “what is the location of the ifconfig program on your manchine”. ...
- ios 版本更新提示-硬更新/软更新
实现: 强制更新:每次弹框 非强制更新:一天提示一次 代码如下: 步骤一: 将检测更新写到APPDelegate的applicationDidBecomeActive中 步骤二: 检测是否需要更新 步 ...
- Python入门看这些,最详细学习书籍推荐
随着人工智能以及脚本开发火热,Python已经被推上一个非常火热的巅峰! 那么,想要学习Python却又不知道从哪里开始的朋友,看这里呀~ Python在整个编程语言来说,是比较容易上手,而且“见效” ...