poj 3237 Tree(树链剖分)
来源:互联网 发布:不编程的app 编辑:程序博客网 时间:2024/05/16 07:26
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
Source
题意:给定一棵树,有3个操作:1、修改某条边权值。2、询问2个节点间最大边权。3、把2个节点间所有边权取相反数
题解:树链剖分。。线段树部分需要lazy。。还挺好写的,不过要注意一下lazy值的维护
#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;const int maxn = 100008;struct edge{ int to,next;}e[maxn<<1];struct segment{ int ma,mi,lazy;}tree[maxn<<2];int head[maxn],d[maxn][3];int dep[maxn],w[maxn],fa[maxn];int top[maxn],son[maxn],siz[maxn];int n,all,root,t,a,b,c,z;char s[18];void add(int x,int y){ e[++all].to=y; e[all].next=head[x]; head[x]=all;}void dfs(int x){ siz[x]=1; son[x]=0; for(int i=head[x];i!=-1;i=e[i].next) { if(e[i].to==fa[x]) continue; fa[e[i].to]=x; dep[e[i].to]=dep[x]+1; dfs(e[i].to); if(siz[e[i].to]>siz[son[x]]) son[x]=e[i].to; siz[x]+=siz[e[i].to]; }}void build_tree(int x,int tp){ w[x]=++z; top[x]=tp; if(son[x]!=0) build_tree(son[x],top[x]); for(int i=head[x];i!=-1;i=e[i].next) { if(e[i].to!=son[x]&&e[i].to!=fa[x]) build_tree(e[i].to,e[i].to); }}void build_segment_tree(int pos,int l,int r){ int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1; tree[pos].lazy=0; tree[pos].ma=-0xffffff; tree[pos].mi=0xffffff; if(l==r) return; build_segment_tree(ls,l,mid); build_segment_tree(rs,mid+1,r);}void make_negate(int pos){ tree[pos].ma=-tree[pos].ma; tree[pos].mi=-tree[pos].mi; swap(tree[pos].ma,tree[pos].mi);}void push_down(int pos){ int ls=pos<<1,rs=pos<<1|1; tree[pos].lazy=0; tree[ls].lazy^=1; tree[rs].lazy^=1; make_negate(ls); make_negate(rs);}void push_up(int pos){ tree[pos].ma=max(tree[pos<<1].ma,tree[pos<<1|1].ma); tree[pos].mi=min(tree[pos<<1].mi,tree[pos<<1|1].mi);}void update(int pos,int l,int r,int loc,int val){ int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1; if(loc>r||loc<l) return; if(l==r){ tree[pos].mi=tree[pos].ma=val; return; } if(tree[pos].lazy) push_down(pos); update(ls,l,mid,loc,val); update(rs,mid+1,r,loc,val); push_up(pos);}int maxi(int pos,int l,int r,int ltemp,int rtemp){ int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1; if(l>rtemp||ltemp>r) return -0xffffff; if(ltemp<=l&&r<=rtemp) return tree[pos].ma; if(tree[pos].lazy) push_down(pos); return max(maxi(ls,l,mid,ltemp,rtemp) ,maxi(rs,mid+1,r,ltemp,rtemp));}int myfind(int va,int vb){ int f1=top[va],f2=top[vb],tmp=-0xffffff; while(f1!=f2) { if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); } tmp=max(tmp,maxi(1,1,z,w[f1],w[va])); va=fa[f1]; f1=top[va]; } if(va==vb) return tmp; if(dep[va]>dep[vb]) swap(va,vb); return max(tmp,maxi(1,1,z,w[son[va]],w[vb]));}void update_negate(int pos,int l,int r,int ltemp,int rtemp){ int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1; if(l>rtemp||ltemp>r) return; //printf("cc %d %d %d %d\n",l,r,ltemp,rtemp); if(ltemp<=l&&r<=rtemp) { tree[pos].lazy^=1; make_negate(pos); return; } if(tree[pos].lazy) push_down(pos); update_negate(ls,l,mid,ltemp,rtemp); update_negate(rs,mid+1,r,ltemp,rtemp); push_up(pos);}void mynegate(int va,int vb){ int f1=top[va],f2=top[vb]; while(f1!=f2) { if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); } update_negate(1,1,z,w[f1],w[va]); va=fa[f1]; f1=top[va]; } if(va==vb) return; if(dep[va]>dep[vb]) swap(va,vb); update_negate(1,1,z,w[son[va]],w[vb]);}int main(){ scanf("%d",&t); while(t--) { memset(head,-1,sizeof(head)); memset(tree,0,sizeof(tree)); memset(siz,0,sizeof(siz)); scanf("%d",&n); root=(n+1)/2; fa[root]=dep[root]=z=all=0; for(int i=1;i<n;i++) { scanf("%d%d%d",&a,&b,&c); d[i][0]=a,d[i][1]=b,d[i][2]=c; add(a,b),add(b,a); } dfs(root); build_tree(root,root); build_segment_tree(1,1,z); for(int i=1;i<n;i++) { if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]); update(1,1,z,w[d[i][1]],d[i][2]); } while(scanf("%s",s),s[0]!='D') { scanf("%d%d",&a,&b); if(s[0]=='Q') printf("%d\n",myfind(a,b)); else if(s[0]=='N') mynegate(a,b); else update(1,1,z,w[d[a][1]],b); } } return 0;}
- 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(树链剖分)
- poj 3237 Tree 树链剖分
- Web 前端性能优化——把 JavaScript 中的对象存储在变量中
- mongoose源码分析系列之listening_sock
- [BZOJ1303][CQOI2009]中位数图
- 超宽带射频信号高速记录回放系统——模拟带宽3GHZ,记录回放速度高达6000MB/S!
- mongoose源码分析系列之active_connections
- poj 3237 Tree(树链剖分)
- Zlib.net 解压压缩 数据流 对应java 使用
- java如何添加外部包
- 对快速排序的分析
- Go语言 1.3主要改动翻译
- Cocos2dx如何引用第三方SO文件(Android NDK)
- 查找svn版本大于当前版本的文件夹
- android网络编程
- 打印日志的10个建议