Tree - POJ 3237 树链刨分
来源:互联网 发布:java web get post 编辑:程序博客网 时间:2024/06/06 03:59
Description
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
CHANGE
i vChange the weight of the ith edge to vNEGATE
a bNegate the weight of every edge on the path from a to bQUERY
a bFind the maximum weight of edges on the path from a to bInput
The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.
Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE
” ends the test case.
Output
For each “QUERY
” instruction, output the result on a separate line.
Sample Input
131 2 12 3 2QUERY 1 2CHANGE 1 3QUERY 1 2DONE
Sample Output
13
题意:给你一棵树,边上有权值,更新操作有将一个路径上的值取反,和更改一个点的值。查询操作查询两个点之间路径的最大边值。
思路:树链刨分,就是线段树敲起来复杂了些。
AC代码如下:
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;struct node1{ int u,v,w;}arr[10010];struct node2{ int u,v,w,next;}edge[20010];struct node3{ int l,r,maxn,minn,lazy;}tree[40010];int T,t,n,m,tot,tot2,Head[10010],INF=1e9;int siz[10010],son[10010],depth[10010],fa[10010],top[10010],p[10010];int W[10010];char s[10];void dfs1(int u){ int i,j,k,v; siz[u]=1; son[u]=0; for(i=Head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(v==fa[u]) continue; depth[v]=depth[u]+1; fa[v]=u; dfs1(v); if(siz[v]>siz[son[u]]) son[u]=v; siz[u]+=siz[v]; }}void dfs2(int u,int f){ int i,j,k,v; p[u]=++tot2; top[u]=f; if(son[u]!=0) dfs2(son[u],f); for(i=Head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(v==fa[u] || v==son[u]) continue; dfs2(v,v); }}void add(int u,int v,int w){ edge[tot].u=u; edge[tot].v=v; edge[tot].w=w; edge[tot].next=Head[u]; Head[u]=tot++;}void up(int tr){ tree[tr].maxn=max(tree[tr*2].maxn,tree[tr*2+1].maxn); tree[tr].minn=min(tree[tr*2].minn,tree[tr*2+1].minn);}void op(int tr){ tree[tr].maxn=-tree[tr].maxn; tree[tr].minn=-tree[tr].minn; swap(tree[tr].maxn,tree[tr].minn);}void down(int tr){ int minn,maxn; if(tree[tr].lazy) { tree[tr].lazy=0; tree[tr*2].lazy=(tree[tr*2].lazy+1)%2; tree[tr*2+1].lazy=(tree[tr*2+1].lazy+1)%2; op(tr*2); op(tr*2+1); }}void build(int l,int r,int tr){ tree[tr].l=l; tree[tr].r=r; tree[tr].lazy=0; if(l==r) { tree[tr].maxn=tree[tr].minn=W[l]; return; } int mi=(l+r)/2; build(l,mi,tr*2); build(mi+1,r,tr*2+1); up(tr);}void update1(int l,int r,int tr){ if(tree[tr].l==l && tree[tr].r==r) { tree[tr].lazy=(tree[tr].lazy+1)%2; op(tr); return; } down(tr); int mi=(tree[tr].l+tree[tr].r)/2; if(r<=mi) update1(l,r,tr*2); else if(l>mi) update1(l,r,tr*2+1); else { update1(l,mi,tr*2); update1(mi+1,r,tr*2+1); } up(tr);}void update2(int id,int tr,int num){ if(tree[tr].l==tree[tr].r) { tree[tr].maxn=tree[tr].minn=num; return; } down(tr); int mi=(tree[tr].l+tree[tr].r)/2; if(id<=mi) update2(id,tr*2,num); else update2(id,tr*2+1,num); up(tr);}int query(int l,int r,int tr){ if(tree[tr].l==l && tree[tr].r==r) return tree[tr].maxn; down(tr); int mi=(tree[tr].l+tree[tr].r)/2; if(r<=mi) return query(l,r,tr*2); else if(l>mi) return query(l,r,tr*2+1); else return max(query(l,mi,tr*2),query(mi+1,r,tr*2+1));}int solve(int u,int v,int type){ int f1=top[u],f2=top[v],k,maxn=-INF; while(f1!=f2) { if(depth[f1]<depth[f2]) { swap(f1,f2); swap(u,v); } if(type==1) update1(p[f1],p[u],1); else maxn=max(maxn,query(p[f1],p[u],1)); u=fa[f1]; f1=top[u]; } if(u==v) return maxn; if(depth[u]>depth[v]) swap(u,v); if(type==1) update1(p[son[u]],p[v],1); else maxn=max(maxn,query(p[son[u]],p[v],1)); return maxn;}int main(){ int i,j,k,u,v,w,pos,ans; scanf("%d",&T); for(t=1;t<=T;t++) { scanf("%d",&n); tot=tot2=0; memset(Head,-1,sizeof(Head)); for(i=1;i<n;i++) { scanf("%d%d%d",&u,&v,&w); arr[i].u=u; arr[i].v=v; arr[i].w=w; add(u,v,w); add(v,u,w); } depth[1]=1; dfs1(1); dfs2(1,1); for(i=1;i<n;i++) { if(arr[i].v==fa[arr[i].u]) swap(arr[i].v,arr[i].u); W[p[arr[i].v]]=arr[i].w; } build(1,tot2,1); while(true) { scanf("%s",s+1); if(s[1]=='C') { scanf("%d%d",&i,&w); update2(p[arr[i].v],1,w); } else if(s[1]=='N') { scanf("%d%d",&u,&v); solve(u,v,1); } else if(s[1]=='Q') { scanf("%d%d",&u,&v); ans=solve(u,v,2); printf("%d\n",ans); } else break; } }}
- Tree - POJ 3237 树链刨分
- poj 3237 Tree
- POJ 3237 Tree 树链剖分
- 【POJ】3237 Tree 树链剖分
- POJ-3237-Tree
- POJ 3237 Tree 树链剖分
- 【树链剖分】 POJ 3237 Tree
- poj 3237 Tree(树链剖分)
- poj 3237 tree
- POJ 3237 Tree (树链剖分)
- poj-3237 Tree
- POJ 3237 Tree 树链剖分
- POJ 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分
- POJ 3237 - Tree(树链剖分)
- poj 3237 Tree 树链剖分
- poj 3237 tree
- C++1001
- Android实用代码七段(五)
- 安卓Notification的几个常见难点
- 关于 tomcat 集群中 session 共享的三种方法
- 焦耳小偷-Joule_thief原理分析
- Tree - POJ 3237 树链刨分
- Win10 把控制面板放到开始菜单-自定义开始菜单
- nexus启动报错----->错误 1067: 进程意外终止。
- Ubuntu wifi已通过硬件禁止解决方案
- 九度oj-1155-鸡兔同笼
- IOS-笔记3(Optional,Array,Dictionary,Range等)
- 页面提交错误,页面间参数传递java.lang.NumberFormatException: null
- [HDU 1272] 小希的迷宫 并查集
- JMS笔记