西安邀请赛-E(树链剖分+线段树)
题目链接:https://nanti.jisuanke.com/t/39272
题意:给一棵树,n个结点,树根为1,n-1条边,每个结点有一个权值。进行3种操作:
1 s t:把1和s之间的最短路径上的所有结点|t。
2 s t:把1和s之间的最短路径上的所有结点&t。
3 s t:把1和s之间的最短路径上的所有结点进行异或,若结果等于t则输出NO,否则输出YES。(不理解的话可以看一下nim博弈论)
思路:很明显的一道题树链剖分题,难的是怎么维护线段树。我们拆成二进制来看,用num[32]维护区间内所有点对应位的1的数量,对于或操作来说,若对应位为1,则区间所有点对应位全改为1,若为0,则不操作; 对于与操作来说,若对应位为0,则区间所有点对应位全为0,若为1,则不操作。而且这两种操作是具有覆盖效果的,那么我们可以用懒惰标记add[i]=1表示该区间第i位全为1,add[i]=-1表示该区间第i位全为0。查询操作时,将查询区间上所有位1的数量模2,即区间异或和的对应位,将其与输入的t比较是否相等即可。
AC代码:
#include<cstdio>
#include<algorithm>
using namespace std; const int maxn=; int cnt1,head[maxn];
int dep[maxn],siz[maxn],fa[maxn],son[maxn],top[maxn],cnt2,id[maxn],w[maxn],wt[maxn],res;
int n,m; struct node1{
int v,nex;
}edge[maxn<<]; void adde(int u,int v){
edge[++cnt1].v=v;
edge[cnt1].nex=head[u];
head[u]=cnt1;
} struct node2{
int l,r,len;
int num[],add[];
}tr[maxn<<]; void pushup(int v){
for(int i=;i<;++i)
tr[v].num[i]=tr[v<<].num[i]+tr[v<<|].num[i];
} void pushdown(int v){
for(int i=;i<;++i){
if(tr[v].add[i]==){
tr[v<<].num[i]=tr[v<<].len;
tr[v<<].add[i]=;
tr[v<<|].num[i]=tr[v<<|].len;
tr[v<<|].add[i]=;
tr[v].add[i]=;
}
if(tr[v].add[i]==-){
tr[v<<].num[i]=;
tr[v<<].add[i]=-;
tr[v<<|].num[i]=;
tr[v<<|].add[i]=-;
tr[v].add[i]=;
}
}
} void build(int v,int l,int r){
tr[v].l=l,tr[v].r=r,tr[v].len=r-l+;
if(l==r){
for(int i=;i<;++i)
if((<<i)&wt[r])
tr[v].num[i]=;
return;
}
int mid=(l+r)>>;
build(v<<,l,mid);
build(v<<|,mid+,r);
pushup(v);
} void update(int v,int l,int r,int op,int k){
if(l<=tr[v].l&&r>=tr[v].r){
if(op==){
for(int i=;i<;++i)
if((<<i)&k){
tr[v].num[i]=tr[v].len;
tr[v].add[i]=;
}
}
else{
for(int i=;i<;++i)
if(!((<<i)&k)){
tr[v].num[i]=;
tr[v].add[i]=-;
}
}
return;
}
pushdown(v);
int mid=(tr[v].l+tr[v].r)>>;
if(l<=mid) update(v<<,l,r,op,k);
if(r>mid) update(v<<|,l,r,op,k);
pushup(v);
} void query(int v,int l,int r){
if(l<=tr[v].l&&r>=tr[v].r){
for(int i=;i<;++i){
if(tr[v].num[i]&)
res^=(<<i);
}
return;
}
pushdown(v);
int mid=(tr[v].l+tr[v].r)>>;
if(l<=mid) query(v<<,l,r);
if(r>mid) query(v<<|,l,r);
} void dfs1(int x,int f,int deep){
fa[x]=f;
dep[x]=deep;
siz[x]=;
int maxson=-;
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].v;
if(y==f) continue;
dfs1(y,x,deep+);
siz[x]+=siz[y];
if(siz[y]>maxson) son[x]=y,maxson=siz[y];
}
} void dfs2(int x,int tp){
id[x]=++cnt2;
wt[cnt2]=w[x];
top[x]=tp;
if(!son[x]) return;
dfs2(son[x],tp);
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].v;
if(y==fa[x]||y==son[x]) continue;
dfs2(y,y);
}
} void updRange(int x,int y,int op,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(,id[top[x]],id[x],op,k);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
update(,id[x],id[y],op,k);
} void qRange(int x,int y){
res=;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
query(,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
query(,id[x],id[y]);
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;++i)
scanf("%d",&w[i]);
for(int i=;i<n;++i){
int x,y;
scanf("%d%d",&x,&y);
adde(x,y);
adde(y,x);
}
dfs1(,,);
dfs2(,);
build(,,n);
while(m--){
int op,s,t;
scanf("%d%d%d",&op,&s,&t);
if(op==||op==)
updRange(,s,op,t);
else{
qRange(,s);
if(res==t) printf("NO\n");
else printf("YES\n");
}
}
return ;
}
西安邀请赛-E(树链剖分+线段树)的更多相关文章
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- BZOJ2243 (树链剖分+线段树)
Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
- 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 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- 数据库连接windows身份验证、sql验证
windows身份验证:"server=.;database=Northwind;Integrated Security=True;" sql验证:"server=.;d ...
- VS的快捷操作
连按两下Tab,生成代码块.修改i为n,再按一次Tab,对应位置自动改变. Ctrl+. 或者 Alt+Enter ctor 连按两下Tab,生成无返回值的构造函数(constructor func ...
- HDU 5113 Black And White ( 2014 北京区预赛 B 、搜索 + 剪枝 )
题目链接 题意 : 给出 n * m 的网格.要你用 k 种不同的颜色填给出的网格.使得相邻的格子颜色不同.若有解要输出具体的方案 分析 : 看似构造.实则搜索.手构构半天没有什么好想法 直接搜就行了 ...
- 使用wait/notify实现生产消费模型
public class A { private Deque<Integer> list = new LinkedList<>(); private int max = 10; ...
- 十七、mysql数据库备份
使用java代码在window环境下实现定时执行Mysql备份与还原 //备份 public void doBackup() { Date currentTime = new Date(); Syst ...
- django分页模块--django-pure-pagination
Django自带有分页的两个类,但是用起来没有第三方这个分页模块方便,下面介绍一下这个模块的使用方法. 1. 安装模块: pip install django-pure-pagination 2. ...
- mybatis延迟加载(Collection)
上篇讲了assocation,同样我们也可以在一对多关系配置的结点中配置延迟加载策略. 结点中也有 select 属性,column 属性. 需求: 完成加载用户对象时,查询该用户所拥有的账户信息. ...
- window 下要运行php,需要编辑php环境变量
参考:https://blog.csdn.net/zhezhebie/article/details/72765262
- CentOS yum安装软件时保留安装包及依赖包或者自动下载安装包及相关依赖包
CentOS上安装某个软件一般都有很多相关的依赖包,当然,这也与我们安装时software selection步骤中选择的版本有关系,我们服务器在安装CentOS时一般选择Basic Web Serv ...
- c++ / % 四舍五入 向上取整ceil 向下取整floor
/ % 四舍五入 向上取整ceil 向下取整floor #include <math.h> double floor(double x); float floorf(float x); ...