树链剖分-链的剖分(线段树维护边权值的更新)
2014-08-04 19:50
274 查看
poj3237
Tree
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:
Input
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 bwith
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 “
Output
For each “
Sample Input
Sample Output
题意:给出一颗树以及边权值,对边权有三种操作:(1)把第i条边的权值改成v;(2)把<u,v>路径上的边权值改为原来的相反数;(3)输出[b]<u,v>路径上的最大权值;[/b]
[b]程序:[/b]
Tree
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 3629 | Accepted: 1017 |
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:
CHANGEi v | Change the weight of the ith edge to v |
NEGATEa b | Negate the weight of every edge on the path from a to b |
QUERYa b | Find the maximum weight of edges on the path from a to b |
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 bwith
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
1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE
Sample Output
1 3
题意:给出一颗树以及边权值,对边权有三种操作:(1)把第i条边的权值改成v;(2)把<u,v>路径上的边权值改为原来的相反数;(3)输出[b]<u,v>路径上的最大权值;[/b]
[b]程序:[/b]
#include"stdio.h" #include"string.h" #include"iostream" #include"map" #include"string" #include"queue" #include"stdlib.h" #include"math.h" #define M 11009 #define eps 1e-10 #define inf 1000000000 #define mod 1000000000 #define INF 1000000000 using namespace std; struct node { int u,v,w,next; }edge[M*2]; int t,head[M]; int son[M];//记录重链中某点的儿子节点,子叶节点的儿子为-1; int fa[M];//记录每个节点的父节点; int num[M];//记录以该节点为根的子树中有多少个节点; int top[M];//记录某条重链中所有节点的最初节点编号; int p[M];//记录某个节点的编号(对原来的节点重新编号) int fp[M];//记录某编号的节点对应的原来的节点编号; int deep[M];//记录某个节点在树中的深度; int a[M];//记录编过号的节点与其父节点之间的边的边权值;维护的线段树是n-1个点 int pos; int Max; void init() { t=pos=0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); } void add(int u,int v) { edge[t].u=u; edge[t].v=v; edge[t].next=head[u]; head[u]=t++; } void dfs(int u,int f,int d) { deep[u]=d; num[u]=1; fa[u]=f; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v!=f) { dfs(v,u,d+1); num[u]+=num[v]; if(son[u]==-1||num[son[u]]<num[v]) son[u]=v; } } } void getpos(int u,int sp) { top[u]=sp; p[u]=pos++; fp[p[u]]=u; if(son[u]==-1)return; getpos(son[u],sp); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(v!=fa[u]&&v!=son[u]) getpos(v,v); } }//以上是求重链 //***************************以下是线段树操作****************************// struct Node { int l,r,flag,maxi,mini; }tree[M*4]; void pushup(int i) { tree[i].maxi=max(tree[i*2].maxi,tree[i*2+1].maxi); tree[i].mini=min(tree[i*2].mini,tree[i*2+1].mini); } void pushdown(int i)//lazy操作 { if(tree[i].l==tree[i].r)return; if(tree[i].flag) { tree[i*2].maxi=-tree[i*2].maxi; tree[i*2].mini=-tree[i*2].mini; swap(tree[i*2].maxi,tree[i*2].mini); tree[i*2].flag^=1; tree[i*2+1].maxi=-tree[i*2+1].maxi; tree[i*2+1].mini=-tree[i*2+1].mini; swap(tree[i*2+1].maxi,tree[i*2+1].mini); tree[i*2+1].flag^=1; tree[i].flag=0; } } void make(int l,int r,int i)//建立线段树 { tree[i].l=l; tree[i].r=r; tree[i].flag=0; if(tree[i].l==tree[i].r) { tree[i].maxi=tree[i].mini=a[tree[i].l]; return; } int mid=(l+r)>>1; make(l,mid,i*2); make(mid+1,r,i*2+1); pushup(i); } void change(int p,int q,int i)//单点更新 { if(tree[i].l==p&&tree[i].r==p) { tree[i].maxi=tree[i].mini=q; tree[i].flag=0; return; } pushdown(i); int mid=(tree[i].l+tree[i].r)>>1; if(p<=mid)change(p,q,i*2); else change(p,q,i*2+1); pushup(i); } void negval(int l,int r,int i)//区间修改为相反数 { if(tree[i].l==l&&tree[i].r==r) { tree[i].maxi=-tree[i].maxi; tree[i].mini=-tree[i].mini; swap(tree[i].maxi,tree[i].mini); tree[i].flag^=1; return; } pushdown(i); int mid=(tree[i].l+tree[i].r)>>1; if(r<=mid) negval(l,r,i*2); else if(l>mid) negval(l,r,i*2+1); else { negval(l,mid,i*2); negval(mid+1,r,i*2+1); } pushup(i); } void query(int l,int r,int i)//区间查找 { if(tree[i].l==l&&tree[i].r==r) { Max=max(Max,tree[i].maxi); return; } pushdown(i); int mid=(tree[i].l+tree[i].r)>>1; if(r<=mid) query(l,r,i*2); else if(l>mid) query(l,r,i*2+1); else { query(l,mid,i*2); query(mid+1,r,i*2+1); } pushup(i); } int findmax(int u,int v)//树形图转换为线段树结构,并查找最大值 { int f1=top[u]; int f2=top[v]; int ans=-inf; while(f1!=f2) { if(deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } Max=-inf; query(p[f1],p[u],1); ans=max(ans,Max); u=fa[f1]; f1=top[u]; } if(v==u)return ans; if(deep[u]>deep[v])swap(u,v); Max=-inf; query(p[son[u]],p[v],1); ans=max(ans,Max); return ans; } void neg(int u,int v)//树形图转换为线段树结构,并修改区间值 { int f1=top[u]; int f2=top[v]; while(f1!=f2) { if(deep[f1]<deep[f2]) { swap(f1,f2); swap(u,v); } negval(p[f1],p[u],1); u=fa[f1]; f1=top[u]; } if(v==u)return; if(deep[u]>deep[v])swap(u,v); negval(p[son[u]],p[v],1); return; } struct Edge { int u,v,w; }e[M]; int main() { int T,i,n; cin>>T; while(T--) { scanf("%d",&n); init(); for(i=1;i<n;i++) { scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w); add(e[i].u,e[i].v); add(e[i].v,e[i].u); } dfs(1,1,0); getpos(1,1); for(i=1;i<n;i++) { if(deep[e[i].u]<deep[e[i].v]) swap(e[i].v,e[i].u); a[p[e[i].u]]=e[i].w; } make(1,pos-1,1); char ch[22]; int x,y; while(scanf("%s",ch),strcmp(ch,"DONE")!=0) { scanf("%d%d",&x,&y); if(ch[0]=='Q') { printf("%d\n",findmax(x,y)); } else if(ch[0]=='C') { change(p[e[x].u],y,1); } else neg(x,y); } } return 0; }
相关文章推荐
- 树链剖分-链的剖分(线段树维护边权值的更新)
- 树链剖分-链的剖分(线段树维护+离线操作)
- 树链剖分-链的剖分(线段树维护+离线操作)
- poj3237(树链剖分边维护+线段树区间更新)
- BZOJ 1798-维护序列seq(线段树区间更新)
- poj(2828)——Buy Tickets(线段树维护点&点更新)
- hdoj1754 I Hate It【线段树区间最大值维护+单点更新】
- POJ 2828 Buy Tickets(线段树单点更新维护)
- Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)
- 【整合】树链剖分模板(线段树维护)
- (Relax 线段树1.1)POJ 3468 A Simple Problem with Integers(线段树子区间更新的维护:集中更新和动态统计子序列中的数据)
- poj 3468 线段树区间更新维护
- 51nod 1819 黑白树 V2 树链剖分维护轻儿子信息+线段树
- uva1232 la4108 skyline (线段树区间更新,维护最值)
- 线段树维护区间最大模板(单结点更新)(1754)
- POJ3237-Tree (树链剖分,线段树区间更新+点更新+区间查询)
- UVA 11992 (维护多棵线段树,区间更新,区间替换)
- BZOJ 4034浅谈树链剖分及线段树维护
- HDU 4267 A Simple Problem with Integers (55棵线段树更新维护)
- 【线段树维护区间编号 && 区间更新】HDU - 4614 Vases and Flowers