解题思路:这道题据说是树链剖分,所以也学习了一下。

http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

不同的是这里是点权值,我按照相似的处理方式,不知道为什么WA了。。。调了好久。。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;const int maxn = 100005;
struct Segment
{int l,r,sum;
}tree[maxn<<2];
struct Edge
{int to,next;
}edge[maxn<<1];
int A[maxn],son[maxn],top[maxn],w[maxn];
int dep[maxn],fa[maxn],size[maxn];
int cnt,num,pre[maxn];
int n,q,idx[maxn];void addedge(int u,int v)
{edge[cnt].to = v;edge[cnt].next = pre[u];pre[u] = cnt++;
}void dfs(int u)
{size[u] = 1;son[u] = 0;int tmp = 0;for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(fa[u] == v) continue;fa[v] = u;dep[v] = dep[u] + 1;dfs(v);size[u] += size[v];if(size[v] > tmp){tmp = size[v];son[u] = v;}}
}void build_tree(int u,int tp)
{w[u] = ++num; top[u] = tp; idx[num] = u;if(son[u] != 0) build_tree(son[u],tp);for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(v == son[u] || fa[u] == v) continue;build_tree(v,v);}
}void build_Segment(int rt,int l,int r)
{tree[rt].l = l, tree[rt].r = r;tree[rt].sum = 0;if(l == r) return;int mid = (l + r) >> 1;build_Segment(rt<<1,l,mid);build_Segment(rt<<1|1,mid+1,r);
}void update(int rt,int pos,int val)
{if(tree[rt].l == tree[rt].r){tree[rt].sum = val;return;}int mid = (tree[rt].l + tree[rt].r) >> 1;if(pos <= mid) update(rt<<1,pos,val);else update(rt<<1|1,pos,val);tree[rt].sum = tree[rt<<1].sum ^ tree[rt<<1|1].sum;
}int query(int rt,int l,int r)
{if(l <= tree[rt].l && tree[rt].r <= r)return tree[rt].sum;int mid = (tree[rt].l + tree[rt].r) >> 1;int ans = 0;if(l <= mid) ans ^= query(rt<<1,l,r);if(mid < r) ans ^= query(rt<<1|1,l,r);return ans;
}int find(int l,int r)
{int f1 = top[l], f2 = top[r];int ans = 0;while(f1 != f2){if(dep[f1] < dep[f2]){swap(f1,f2);swap(l,r);}ans ^= query(1,w[f1],w[l]);l = fa[f1], f1 = top[l];}if(l == r) return ans^A[f1];if(dep[l] > dep[r]) swap(l,r);return ans ^= query(1,w[son[l]],w[r])^A[f1];
}int main()
{int t,u,v,op;scanf("%d",&t);while(t--){scanf("%d%d",&n,&q);memset(pre,-1,sizeof(pre));cnt = num = 0;for(int i = 1; i < n; i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}dep[1] = 0;dfs(1);build_tree(1,1);build_Segment(1,1,num);for(int i = 1; i <= n; i++){scanf("%d",&A[i]);A[i]++;update(1,w[i],A[i]);}for(int i = 1; i <= q; i++){scanf("%d%d%d",&op,&u,&v);if(op == 0){A[u] = v + 1;update(1,w[u],A[u]);}else {int ans = find(u,v);printf("%d\n",ans-1);}}}return 0;
}

PS:今天早上把这道题给A了,参考了一下别人的代码,发现自己的代码不一样的地方就是在find函数里,我是按照边更新的方式去写的,而这道题是点更新。关键是最后f1=f2后,如何把根节点加入进去。但仔细想想还是没明白我的为什么错了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;const int maxn = 100005;
struct Segment
{int l,r,sum;
}tree[maxn<<2];
struct Edge
{int to,next;
}edge[maxn<<1];
int A[maxn],son[maxn],top[maxn],w[maxn];
int dep[maxn],fa[maxn],size[maxn];
int cnt,num,pre[maxn];
int n,q;void addedge(int u,int v)
{edge[cnt].to = v;edge[cnt].next = pre[u];pre[u] = cnt++;
}void dfs(int u)
{size[u] = 1;son[u] = 0;int tmp = 0;for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(fa[u] == v) continue;fa[v] = u;dep[v] = dep[u] + 1;dfs(v);size[u] += size[v];if(size[v] > tmp){tmp = size[v];son[u] = v;}}
}void build_tree(int u,int tp)
{w[u] = ++num; top[u] = tp;if(son[u] != 0) build_tree(son[u],tp);for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(v == son[u] || fa[u] == v) continue;build_tree(v,v);}
}void build_Segment(int rt,int l,int r)
{tree[rt].l = l, tree[rt].r = r;tree[rt].sum = 0;if(l == r) return;int mid = (l + r) >> 1;build_Segment(rt<<1,l,mid);build_Segment(rt<<1|1,mid+1,r);
}void update(int rt,int pos,int val)
{if(tree[rt].l == tree[rt].r){tree[rt].sum = val;return;}int mid = (tree[rt].l + tree[rt].r) >> 1;if(pos <= mid) update(rt<<1,pos,val);else update(rt<<1|1,pos,val);tree[rt].sum = tree[rt<<1].sum ^ tree[rt<<1|1].sum;
}int query(int rt,int l,int r)
{if(l <= tree[rt].l && tree[rt].r <= r)return tree[rt].sum;int mid = (tree[rt].l + tree[rt].r) >> 1;int ans = 0;if(l <= mid) ans ^= query(rt<<1,l,r);if(mid < r) ans ^= query(rt<<1|1,l,r);return ans;
}int find(int l,int r)
{int f1 = top[l], f2 = top[r];int ans = 0;while(f1 != f2){if(dep[f1] < dep[f2]){swap(f1,f2);swap(l,r);}ans ^= query(1,w[f1],w[l]);l = fa[f1], f1 = top[l];}if(dep[l] > dep[r]) swap(l,r);<span style="white-space:pre">   </span>//没有比较l与r,这是关键点return ans ^= query(1,w[l],w[r]);
}int main()
{int t,u,v,op;scanf("%d",&t);while(t--){scanf("%d%d",&n,&q);memset(pre,-1,sizeof(pre));cnt = num = 0;for(int i = 1; i < n; i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}dep[1] = 0;dfs(1);build_tree(1,1);build_Segment(1,1,num);for(int i = 1; i <= n; i++){scanf("%d",&A[i]);update(1,w[i],A[i]+1);}for(int i = 1; i <= q; i++){scanf("%d%d%d",&op,&u,&v);if(op == 0)update(1,w[u],v+1);else {int ans = find(u,v);printf("%d\n",ans-1);}}}return 0;
}

hdu 5274(树链剖分)相关推荐

  1. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  2. hdu 3966( 树链剖分+点权更新)

    题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上的所有点权值加上K D C1 C2 K:把C1与C2的路径上的所有点权值减去K Q C:查询节点编号为C ...

  3. HDU 3966 树链剖分后线段树维护

    题意: 一棵树, 操作1.$path(a,b)$之间的点权$+k$ 操作2.单点查询 题解: 树链剖分即可,注意代码细节,双向映射 主要是记录一下板子 #include <string.h> ...

  4. HDU 5405 (树链剖分+线段树)

    Problem Sometimes Naive 题目大意 给你一棵n个节点的树,有点权. 要求支持两种操作: 操作1:更改某个节点的权值. 操作2:给定u,v, 求 Σw[i][j]   i , j ...

  5. hdu 5052 树链剖分+线段树+区间合并

    各种裸,但合在一起好恶心... 因为路径是有向的,所以要维护区间里向两个方向走的最大收益和区间里的最大最小值,要用到区间合并的线段树 #include <iostream> #includ ...

  6. HDU 5274 Dylans loves tree(树链剖分)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5274 [题目大意] 给出一棵树,每个点有一个权值,权值可修改,且大于等于0,询问链上出现次数为奇数 ...

  7. HDU - 3966 Aragorn's Story(树链剖分)

    题目传送门:HDU - 3966 Aragorn's Story 题目大意: 存在一个树,树上每个节点为一个阵营,阵营中存在敌人,现在要进行以下操作 I  C1  C2  K :将阵营C1到阵营C2路 ...

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

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

  9. HDU 3966 POJ 3237 HYSBZ 2243 HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

最新文章

  1. c语言一对圆括号不能,C语言单元习题集
  2. Hibernate Shards 数据的水平、垂直切割(二)- Hibernate Shards基本演示
  3. 大规模推荐Deep Retrieval
  4. 报错:Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
  5. 2019 AI Bootcamp·Guangzhou 参会日记
  6. 仿B站(一) 目的分析以及创建 WebAPI + Angular7 项目
  7. mac的python怎么输入中文_无法在python IDE(Mac OS X)中输入unicode
  8. vs2005手机开发环境的配置
  9. Linux入门(1)_VMware和系统分区和系统安装和远程登陆管理
  10. 网络管理 之 Fedora Core 网络配置工具system-config-network介绍
  11. 多个字段排序_SQL | 汇总分析、排序、运行顺序
  12. django-rest-framework二--权限(转载)
  13. Python制作反编译APK工具
  14. mysql中FIND_IN_SET函数用法
  15. 【lua编程 控制手机进行聊天】--用于养号、可以放下手进行自动化聊天养号了
  16. 小米路由修改服务器密码,192.168.31.1小米路由器修改WIFI密码
  17. (设计模式)Adaptor、Decorator与Facade模式
  18. Ubuntu 有望成为最jia Linux 游戏桌面
  19. python reset_HTML DOM reset() 方法
  20. 2021上海最新购房政策指南!买房、贷款、限购究竟有哪些变化?

热门文章

  1. 重磅!神策客户服务中心升级,5 年,价值释放加速度
  2. 自动化测试|录制回放效果差异检测
  3. redux-form(V7.4.2)笔记(二)
  4. jenkins~管道Pipeline里使用公用类库
  5. Symfony2中的命名约定
  6. Nutanix 将社区版代码带入云中
  7. 和我一起学《HTTP权威指南》——安全HTTP与HTTPS
  8. IT十八掌作业_java基础第二天_进制转换原理和补码存储方式
  9. windows server 2008 r2之间的ftp传输脚本
  10. cisco stp技术应用