题目链接: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(树链剖分+线段树)的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

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

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. 【bug解决】ios微信浏览器中背景音乐无法播放

    我记得之前在一次项目中,出现过浏览报错: 当时的文档链接如右:[解决]HTML5新标签audio的autoplay自动播放属性失效的解决方案 所以在这次H5的制作中,我使用了iframe来加载音频文件 ...

  2. 在Ubuntu 18.04系统中蓝牙鼠标连接失败问题的解决

    2018-08-22 16:00:35作者:谖瓞稿源:linux站 如果你在Ubuntu 18.04操作系统中有蓝牙鼠标连接失败问题,那就参考下面的解决方法处理. 解决方法 首先在系统终端下输入: b ...

  3. java常见问题 ——运行报错1

    错误1 打印乱码 相关代码 response.getWriter().print(tbItem.toString()); response.setContentType("text/html ...

  4. python学习用到的网站

    官方地址:https://www.python.org/ 玩蛇网:http://www.iplaypython.com/

  5. bootstrap面板的使用

    <div class="panel panel-primary"> <div class="panel-heading"> 头部 < ...

  6. jsPDF – 基于 HTML5 的强大 PDF 生成工具

    jsPDF 是一个基于 HTML5 的客户端解决方案,用于生成各种用途的 PDF 文档. 使用方法很简单,只要引入 jsPDF 库,然后调用内置的方法就可以了. 米扑科技项目用到了HHTML5生成PD ...

  7. AtCoder AGC005E Sugigma: The Showdown (博弈论)

    题目链接 https://atcoder.jp/contests/agc005/tasks/agc005_e 题解 完了真的啥都不会了-- 首先,显然如果某条A树的边对应B树上的距离大于等于\(3\) ...

  8. From 7.15 To 7.21

    From 7.15 To 7.21 大纲 竞赛 一周七天, 总共做三十五到四十道题吧, 题解要一起写了, 周六之前写不完的话就只能回家补咯 加上考试题总共做了25道题... 还要学计算几何, 生成函数 ...

  9. Keras学习笔记二:保存本地模型和调用本地模型

    使用深度学习模型时当然希望可以保存下训练好的模型,需要的时候直接调用,不再重新训练 一.保存模型到本地 以mnist数据集下的AutoEncoder 去噪为例.添加: file_path=" ...

  10. leetcode题目4.寻找两个有序数组的中位数(困难)

    题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和  ...