2019 ACM-ICPC 西安全国邀请赛 E-Tree 树链剖分+线段树
题意
给一颗带点权的树,三种操作
- \(1~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]|t\)
- \(2~s~t\) 修改从1到s的路径上的所有点,\(a[i]=a[i]\&t\)
- \(3~s~t\) 询问将1到s的路径上的所有点作为石头堆,再加上一个个数为\(t\)的石头堆,进行一次尼姆博弈,先手胜利输出YES,否则输出NO
分析
尼姆博弈先手必胜条件为所有石头堆异或和为0,将询问转化为求1到s的路径上的所有点的异或和,
先树链剖分一下给每个点重新编号,然后线段树维护区间异或和
怎么维护区间异或和?对二进制的每一位建一颗线段树维护区间和(当前二进制位为1的数量),若区间和为奇数说明这一位的区间异或结果为1,否则为0
怎么修改?
修改1为区间或操作:对于二进制的第\(i\)位,若\(t\)的二进制第\(i\)位为1,则会将从1到s的路径上的点权的二进制第\(i\)位全变为1,若\(t\)的二进制第\(i\)位为0,则无影响
修改2为区间与操作:对于二进制的第\(i\)位,若\(t\)的二进制第\(i\)位为0,则会将从1到s的路径上的点权的二进制第\(i\)位全变为0,若\(t\)的二进制第\(i\)位为1,则无影响
Code
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define lson l,mid,p<<1
#define rson mid+1,r,p<<1|1
#define ll long long
using namespace std;
const int inf=1e9;
const int mod=1e9+7;
const int maxn=1e5+10;
int n,q;
int a[maxn];
vector<int>g[maxn];
int sz[maxn],son[maxn],f[maxn],d[maxn],top[maxn],p[maxn],tot;
struct ppo{
int tr[maxn<<2],tag[maxn<<2];
void clear(){memset(tag,-1,sizeof(tag));}
void pp(int p){
tr[p]=(tr[p<<1]+tr[p<<1|1]);
}
void pd(int l,int r,int p,int k){
tr[p]=(r-l+1)*k;tag[p]=k;
}
void up(int dl,int dr,int l,int r,int p,int k){
if(l>=dl&&r<=dr){
tr[p]=(r-l+1)*k;tag[p]=k;return;
}int mid=(l+r)>>1;
if(~tag[p]){pd(lson,tag[p]);pd(rson,tag[p]);tag[p]=-1;}
if(dl<=mid) up(dl,dr,lson,k);
if(dr>mid) up(dl,dr,rson,k);
pp(p);
}
int qy(int dl,int dr,int l,int r,int p){
if(l>=dl&&r<=dr){
return tr[p]&1;
}int mid=(l+r)>>1;int ret=0;
if(~tag[p]){pd(lson,tag[p]);pd(rson,tag[p]);tag[p]=-1;}
if(dl<=mid) ret^=qy(dl,dr,lson);
if(dr>mid) ret^=qy(dl,dr,rson);
return ret;
}
}seg[33];
void add(int x){
int k=a[x];
for(int i=0;i<=30;i++) seg[i].up(p[x],p[x],1,n,1,(k>>i)&1);
}
void dfs1(int u){
sz[u]=1;d[u]=d[f[u]]+1;
for(int x:g[u]){
if(x==f[u]) continue;
f[x]=u;dfs1(x);
sz[u]+=sz[x];
if(sz[x]>sz[son[u]]) son[u]=x;
}
}
void dfs2(int u,int t){
top[u]=t;p[u]=++tot;add(u);
if(son[u]) dfs2(son[u],t);
for(int x:g[u]){
if(x==f[u]||x==son[u]) continue;
dfs2(x,x);
}
}
void gao(int x,int y,int s,int k){
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
seg[s].up(p[top[x]],p[x],1,n,1,k);x=f[top[x]];
}
if(d[x]<d[y]) swap(x,y);
seg[s].up(p[y],p[x],1,n,1,k);
}
int cal(int x,int y,int s){
int ret=0;
while(top[x]!=top[y]){
if(d[top[x]]<d[top[y]]) swap(x,y);
ret^=seg[s].qy(p[top[x]],p[x],1,n,1);
x=f[top[x]];
}
if(d[x]<d[y]) swap(x,y);
return seg[s].qy(p[y],p[x],1,n,1)^ret;
}
int main(){
//ios::sync_with_stdio(false);
//freopen("in","r",stdin);
scanf("%d%d",&n,&q);
for(int i=0;i<=30;i++) seg[i].clear();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=2,a,b;i<=n;i++){
scanf("%d%d",&a,&b);
g[a].push_back(b);
g[b].push_back(a);
}
dfs1(1);dfs2(1,1);
while(q--){
int op,s,t;
scanf("%d%d%d",&op,&s,&t);
if(op==1){
for(int i=0;i<=30;i++)
if((t>>i)&1) gao(1,s,i,1);
}else if(op==2){
for(int i=0;i<=30;i++)
if(!((t>>i)&1)) gao(1,s,i,0);
}else{
int ans=0;
for(int i=0;i<=30;i++)
if(cal(1,s,i)) ans|=(1<<i);
if(ans^t) puts("YES");
else puts("NO");
}
}
return 0;
}
2019 ACM-ICPC 西安全国邀请赛 E-Tree 树链剖分+线段树的更多相关文章
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- 【POJ3237】Tree(树链剖分+线段树)
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
- 2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)
链接:https://ac.nowcoder.com/acm/contest/553/I 思路:离线整棵树,用并查集维护下联通的情况,因为值只有60个,用2的x(1<=x<=60)次方表示 ...
- POJ3237 Tree 树链剖分 线段树
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ3237 题意概括 Description 给你由N个结点组成的树.树的节点被编号为1到N,边被编号为1 ...
- 【CF725G】Messages on a Tree 树链剖分+线段树
[CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...
- Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- Water Tree CodeForces 343D 树链剖分+线段树
Water Tree CodeForces 343D 树链剖分+线段树 题意 给定一棵n个n-1条边的树,起初所有节点权值为0. 然后m个操作, 1 x:把x为根的子树的点的权值修改为1: 2 x:把 ...
- spoj QTREE - Query on a tree(树链剖分+线段树单点更新,区间查询)
传送门:Problem QTREE https://www.cnblogs.com/violet-acmer/p/9711441.html 题解: 树链剖分的模板题,看代码比看文字解析理解来的快~~~ ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- poj 3237 Tree 树链剖分+线段树
Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...
随机推荐
- [LOJ#3119][Luogu5405][CTS2019]氪金手游(DP+容斥)
先考虑外向树的做法,显然一个点在其子树内第一个出现的概率等于它的权值除以它子树的权值和.于是f[i][j]表示i的子树的权值和为j时,i子树内所有数的相互顺序都满足条件的概率,转移直接做一个背包卷积即 ...
- JavaScript中数组的key-value在对象中倒装的妙用
对于数组的去重.寻找指定元素的索引,通常我们都是通过遍历来解决,但是在某些应用场景下,将数组的value-key进行倒装,也即将value当做对象的key,key当做对象value,可以极大降低算法的 ...
- Hadoop1-认识Hadoop大数据处理架构
一.简介概述 1.什么是Hadoop Hadoop是Apache软件基金会旗下的一个开源分布式计算平台,为用户提供了系统底层细节透明的分布式基础架构 Hadoop是基于java语言开发,具有很好的跨平 ...
- 1.1 文档PUT内部原理
文档更新原理: PUT 一条数据的时候,如果是全量替换,ES并不会覆盖原来的文档,而是新创建一个文档,并将version+1,原文档标记为deleted,不会立刻物理删除.ES会在集群的d ...
- 【洛谷 P2051】 [AHOI2009]中国象棋(DP)
题目链接 首先想到状压dp,但是\(n,m\)高达100,怎么压? 容易发现,每行每列最多两个象棋,否则就直接gg了. 一个巧妙的设置状态的方式是,只需要记录到当前行有多少列是放了1个炮和2个炮. 然 ...
- JavaScript函数参数传递
Hello,今天和大家分享下JS中的一个基本概念:函数参数传递! 先来看看一个DEMO var str="hello world"; function func(s){ s=&qu ...
- 经典数据结构与算法在经典软件(linux kernel)中的应用
参考文章:Core Alorgithms deployed linux中的priority search tree数据结构研究 虚拟内存: 1.红黑树,管理与进程关联的vm_area_struct实例 ...
- 【大数据技术能力提升_4】logistic学习
logistic学习 标签(空格分隔): logistic sigmod函数 逻辑回归 分类 前言: 整体逻辑回归比线性回归难理解点,其还需要<概率论与数理统计>中"二项分布 ...
- centos7小命令
修改时区:timedate [root@centos2 ~]# timedatectl set-timezone Asia/Shanghai 修改语言:localectl [root@centos2 ...
- 搭建MySQL MMM高可用
搭建MMM: 1,安装 agent 节点执行 yum install -y mysql-mmm-agent 2, monitor 节点执行 yum install -y mysql-mmm-monit ...