题目

又是一个条历新年,窗前的灼之花又盛开了。

时隔多年,现在只有这一棵树上盛开着残存的 \(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'\) ;

灼之花一齐盛开的景象令人过目难忘,其美丽值为每对生长在不同枝杈的相同颜色的灼之花的光亮值的异或和:

\[\sum_{u,v,c_u=c_v,\\ \operatorname{LCA}(u,v)\not=u,\\\operatorname{LCA}(u,v)\not=v}l_u\oplus l_v
\]

数据范围: \(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}\) 的限制。

不难发现,我们只需要减去下列不合法的点即可:

  1. 对应点在根到当前点的路径上

  2. 对应点在当前点的子树内

第一个部分可以考虑维护贡献,等价于每次修改子树,也就是 DFS 序上的一段区间,区间加 - 单点查。

第二个部分可以考虑统计贡献,直接在 DFS 序上面维护,单点加 - 区间查。

如果需要在线算法,就可以用维护 \(n\) 个 \(splay\) ,分别维护 \(n\) 种颜色的点的部分 DFS 序。

如果需要离线算法,就可以直接使用整棵树的 DFS 序,然后用 4 个 BIT 分别维护。

时间复杂度 \(O(m\log_2n\log_2l)\) 。

本题的一些有价值的点:

  1. 对于变化操作的拆分,转化为简单的情形。
  2. 统计贡献维护贡献两种思想。

代码

由于这是模拟赛里面的题目,所以没有处理多组数据。

#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的更多相关文章

  1. 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 ...

  2. hdu6035 Colorful Tree 树形dp 给定一棵树,每个节点有一个颜色值。定义每条路径的值为经过的节点的不同颜色数。求所有路径的值和。

    /** 题目:hdu6035 Colorful Tree 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6035 题意:给定一棵树,每个节点有一个颜色值.定 ...

  3. AtCoder Beginner Contest 133 F Colorful Tree

    Colorful Tree 思路: 如果强制在线的化可以用树链剖分. 但这道题不强制在线,那么就可以将询问进行差分,最后dfs时再计算每个答案的修改值, 只要维护两个数组就可以了,分别表示根节点到当前 ...

  4. HDU 6035 - Colorful Tree | 2017 Multi-University Training Contest 1

    /* HDU 6035 - Colorful Tree [ DFS,分块 ] 题意: n个节点的树,每个节点有一种颜色(1~n),一条路径的权值是这条路上不同的颜色的数量,问所有路径(n*(n-1)/ ...

  5. Colorful tree

    cnbb 我被数组清零卡了一天.. 子树改色询问子树颜色数.. 先考虑颜色为x的节点对祖先答案的贡献,那么我们考虑把所有这些节点都搞出来,按dfs序排序,然后考虑每个节点a掌管的祖先是它和按dfs序的 ...

  6. 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 ...

  7. HDU-6035:Colorful Tree(虚树+DP)

    这里有三道长得像的题: 一:HDU6036: There is a tree with nn nodes, each of which has a type of color represented ...

  8. ABC133F - Colorful Tree

    ABC133FColorful Tree 题意 给定一颗边有颜色和权值的树,多次询问,每次询问,首先更改颜色为x的边的权值为y,然后输出u到v的距离. 数据都是1e5量级的. 思路 我自己一开始用树链 ...

  9. HDU6035 Colorful Tree

    题目链接:https://vjudge.net/problem/HDU-6035 题目大意: 多样例输入. 对于每一个样例,给出 n \((2 \le n \le 200000)\) 个结点的一棵树, ...

随机推荐

  1. LQB2013A02排它平方数

    这个题方向其实还算好找,就是枚举嘛 (这是一个填空题,所以六个for嵌套也无所谓,因为毕竟emmmm,不看时间) 这里是判断的代码: 需要把数字转化成字符串 void i2s(int x,string ...

  2. python基础day4_列表list

    list列表 li = ['alex',[1,2,3],'hjh','nvshen '] l1= li[0] print(l1) # alex l3= li[0:3]#['alex', [1, 2, ...

  3. PHP is_uploaded_file() 函数

    定义和用法 is_uploaded_file() 函数检查指定的文件是否是通过 HTTP POST 上传的. 如果文件是通过 HTTP POST 上传的,该函数返回 TRUE. 语法 is_uploa ...

  4. 阿里云Redis的开发规范

    作者:付磊-起扬 来源:https://yq.aliyun.com/articles/531067 本文主要介绍在使用阿里云Redis的开发规范,从下面几个方面进行说明. 键值设计 命令使用 客户端使 ...

  5. Rest接口加Https单向认证

    背景: 接到一个需求,客户要求某个模块的rest接口都得通过https访问,客户提供证书. 步骤: Server端证书生成 刚开始还没拿到客户的证书,所以通过jdk自带的keytools自己先生成了一 ...

  6. 15、Java中级进阶 面向对象 继承

    1.何为面向对象 其本质是以建立模型体现出来的抽象思维过程和面向对象的方法(百度百科)是一种编程思维,也是一种思考问题的方式 如何建立面向对象的思维呢?1.先整体,再局部2.先抽象,再具体3.能做什么 ...

  7. SpringBoot学习之整合Swagger

    Swagger介绍 1.什么是Swagger 作为后端程序开发,我们多多少少写过几个后台接口项目,不管是编写手机端接口,还是目前比较火热的前后端分离项目,前端与后端都是由不同的工程师进行开发,那么这之 ...

  8. Springboot日志LOGO改变和设计

    每次启动Springboot的时候,SpringBoot都会打印一个LOGO,那么这个LOGO是可以关闭和改变的. 1.关闭Springboot的LOGO 2.改变Springboot的日志LOGO ...

  9. 面试官:怎么做JDK8的垃圾收集器的调优?

    面试官:怎么做JDK8的垃圾收集器的调优? 看着面试官真诚的眼神,心中暗想看起来年纪轻轻却提出如此直击灵魂的问题.擦了擦额头上汗,我稍微调整了一下紧张的情绪,对面试官说: 在JDK8中有Serial收 ...

  10. 靶机练习 - ATT&CK红队实战靶场 - 1. 环境搭建和漏洞利用

    最近某个公众号介绍了网上的一套环境,这个环境是多个Windows靶机组成的,涉及到内网渗透,正好Windows和内网渗透一直没怎么接触过,所以拿来学习下. 下载地址:http://vulnstack. ...