poj 3237 线段树+树链剖分
来源:互联网 发布:id软件怎么用 编辑:程序博客网 时间:2024/05/16 07:22
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
题意:给一棵树,三种操作。将第i条边的权值改为v,将a到b的路径上的边的权值全部取反,求a到b路径上边的权值的最大值。
思路:明显的树链剖分,加上线段树的操作。因为有取反的操作所以每个区间要记录最大值和最小值。查询两点间的路径时,用求公共祖先的方式去求。
#include<stdio.h>#include<algorithm>#include<string.h>#define N 20005#define inf 0x3fffffffusing namespace std;struct line{ int x,y,w;}ed[N];struct node{ int u,v,w,next;}bian[N*2];struct pp{ int x,y,ma,mi,p;}a[N*3];int e,id;int sz[N],dep[N],head[N],top[N],son[N],father[N],ti[N];int max(int a,int b){ return a>b?a:b;}int min(int a,int b){ return a<b?a:b;}void add(int u,int v,int w){ bian[e].u=u; bian[e].v=v; bian[e].w=w; bian[e].next=head[u]; head[u]=e++;}void dfs1(int u,int fa){ int i,v; sz[u]=1; dep[u]=dep[fa]+1; son[u]=0; father[u]=fa; for(i=head[u];i!=-1;i=bian[i].next) { v=bian[i].v; if(v==fa) continue; dfs1(v,u); sz[u]+=sz[v]; if(sz[son[u]]<sz[v]) son[u]=v; }}void dfs2(int u,int fa){ int i,v; top[u]=fa; ti[u]=id++; if(son[u]!=0) dfs2(son[u],fa); for(i=head[u];i!=-1;i=bian[i].next) { v=bian[i].v; if(v==son[u]||v==father[u]) continue; dfs2(v,v); }}void pushdown(int t){ int temp=t<<1; a[t].ma=max(a[temp].ma,a[temp+1].ma); a[t].mi=min(a[temp].mi,a[temp+1].mi);}void build(int t ,int x,int y){ a[t].x=x; a[t].y=y; a[t].ma=a[t].mi=a[t].p=0; if(x==y) return; int mid=(x+y)>>1,temp=t<<1; build(temp,x,mid); build(temp+1,mid+1,y);}void find(int t){ int temp=t<<1; if(a[t].p) { a[temp].ma=-a[temp].ma; a[temp].mi=-a[temp].mi; swap(a[temp].ma,a[temp].mi); a[temp+1].ma=-a[temp+1].ma; a[temp+1].mi=-a[temp+1].mi; swap(a[temp+1].ma,a[temp+1].mi); a[temp].p^=1; a[temp+1].p^=1; a[t].p=0; }}int query(int t,int x,int y)//查询线段树中[x,y]的最大值{ int ma; if(a[t].x==x&&a[t].y==y) return a[t].ma; int mid=(a[t].x+a[t].y)>>1,temp=t<<1; find(t); if(y<=mid) return query(temp,x,y); else if(x>mid) return query(temp+1,x,y); else return max(query(temp,x,mid),query(temp+1,mid+1,y));}int lca(int x,int y)//返回最大值{ int ans; ans=-inf; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); ans=max(ans,query(1,ti[top[x]],ti[x])); x=father[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(x!=y) ans=max(ans,query(1,ti[x]+1,ti[y])); return ans;}void update(int t ,int x,int w)//更新线段树的第x个值为w{ if(a[t].x==a[t].y) { a[t].ma=a[t].mi=w; a[t].p=0; return; } int mid=(a[t].x+a[t].y)>>1,temp=t<<1; find(t); if(x<=mid) update(temp,x,w); else update(temp+1,x,w); pushdown(t);}void reupdate(int t,int x,int y)//更新线段树的区间[x,y]取反{ if(a[t].x==x&&a[t].y==y) { a[t].ma=-a[t].ma; a[t].mi=-a[t].mi; swap(a[t].ma,a[t].mi); a[t].p^=1; return ; } int mid=(a[t].x+a[t].y)>>1,temp=t<<1; find(t); if(y<=mid) reupdate(temp,x,y); else if(x>mid) reupdate(temp+1,x,y); else { reupdate(temp,x,mid); reupdate(temp+1,mid+1,y); } pushdown(t);}void relca(int x,int y)//把x到y路径上的值都取反{ while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); reupdate(1,ti[top[x]],ti[x]); x=father[top[x]]; } if(dep[x]>dep[y]) swap(x,y); if(x!=y) reupdate(1,ti[x]+1,ti[y]);}int main(){ int t,i,x,y,v,n; char str[100]; scanf("%d",&t); while(t--) { scanf("%d",&n); e=0; memset(head,-1,sizeof(head)); for(i=1;i<n;i++) { scanf("%d%d%d",&ed[i].x,&ed[i].y,&ed[i].w); add(ed[i].x,ed[i].y,ed[i].w); add(ed[i].y,ed[i].x,ed[i].w); } dep[1]=0; id=1; sz[0]=0; dfs1(1,1); dfs2(1,1); //for(i=1;i<=n;i++) // printf("i=%d size=%d top=%d father=%d son=%d ti=%d dep=%d\n",i,sz[i],top[i],father[i],son[i],ti[i],dep[i]); build(1,1,n); for(i=1;i<n;i++) { if(dep[ed[i].x]<dep[ed[i].y]) swap(ed[i].x,ed[i].y); update(1,ti[ed[i].x],ed[i].w); } while(scanf("%s",str),strcmp(str,"DONE")!=0) { if(str[0]=='Q') { scanf("%d%d",&x,&y); printf("%d\n",lca(x,y));//查询x->y路径上边权的最大值 } else if(str[0]=='N') { scanf("%d%d",&x,&y); relca(x,y); } else if(str[0]=='C') { scanf("%d%d",&i,&v);//改变第i条边的值为v update(1,ti[ed[i].x],v); } } } return 0;}
- poj 3237(树链剖分+线段树)
- poj 3237 线段树+树链剖分
- poj 3237 树链剖分+线段树
- 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(树链剖分+线段树)
- poj 3237 树链剖分模板(用到线段树lazy操作)
- POJ 3237 Tree(树链剖分 线段树区间标记)
- poj 3237 Tree(树链剖分,点权,线段树)
- 【POJ】【P3237】【Tree】【题解】【树链剖分+线段树】
- POJ 2763 Housewife Wind (树链剖分+线段树)
- POJ 2777 线段树
- 关于VMware虚拟机中的Ubuntu 12-04不能连接网络的一种解决方法
- jira 6.0.7 linux安装
- 判断这俩个链表是否相交
- hdu 2549 壮志难酬
- tomcat的安全配置
- poj 3237 线段树+树链剖分
- 在IOS应用中打开另外一个应用的解决方案
- fancybox关闭弹出窗口parent.$.fancybox.close();
- mysql 5.0存储过程学习总结
- 全球视觉计算技术的行业领袖- NVIDIA--火热招聘
- Thread题不知道错在了那里
- win7 启用共享连接访问失败的解决办法·
- 后会无期,袁泉克制体:有wifi就会放肆,用流量就会克制
- TQ2440之内核3.15.6移植