日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

hdu 5274(树链剖分)

發布時間:2025/3/16 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu 5274(树链剖分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解題思路:這道題據說是樹鏈剖分,所以也學習了一下。

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(树链剖分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。