POJ 3237 Tree (树链剖分+线段树)
2015-02-03 19:20
316 查看
题目链接:POJ 3237 Tree
题意:在树上有三种操作。
CHANGE A B 1.将第A条边的值赋值为B;
NEGATE A B 2.将A节点到B节点路径上的边变为其相反数。
QUERY A B 3.访问A节点到B节点的路径上的边权最大。
比较明显的树链剖分,主要是在线段树区间更新,取相反数可以得到,最大值和最小值取相反数后,再交换就是各自改变后的值。
AC代码:
题意:在树上有三种操作。
CHANGE A B 1.将第A条边的值赋值为B;
NEGATE A B 2.将A节点到B节点路径上的边变为其相反数。
QUERY A B 3.访问A节点到B节点的路径上的边权最大。
比较明显的树链剖分,主要是在线段树区间更新,取相反数可以得到,最大值和最小值取相反数后,再交换就是各自改变后的值。
AC代码:
#include <string.h> #include <stdio.h> #include <algorithm> #define IN freopen ("in.txt" , "r" , stdin); using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100010+10; const int inf=100000000; struct Edge{ int to,next; }; struct Edge edge[maxn*2]; int head[maxn],tot; int stree[maxn];//节点v在线段树上的编号 int pre[maxn];//在线段树中编号为v节点所对应原图中的编号。 int fa[maxn];//f[v] 表示v的父亲节点 int son[maxn];//表示 与v同在一重链上的儿子节点(重儿子) int num[maxn];//num[v] v为根的子树的节点数。 int top[maxn];//top[v] v所在链的顶端节点。 int deep[maxn];//deep[v] 表示v的深度(根的深度为1) int data[maxn]; int pos,n; void addedge(int u,int v){ edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void dfs1(int u,int father,int dep){ int i; deep[u]=dep; fa[u]=father; num[u]=1; for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v!=father){ dfs1(v,u,dep+1); num[u]+=num[v]; if(son[u]==-1 || num[v]>num[son[u]]){ son[u]=v; } } } } //给点编号得到线段树上的对应标号 void getpos(int u,int sp){ int i; top[u]=sp; stree[u]=pos++; pre[stree[u]]=u; if(son[u]==-1) return ; getpos(son[u],sp); for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v!=son[u] && v!=fa[u]){ getpos(v,v); } } } void init(){ tot=0; memset(head,-1,sizeof head); pos=0; memset(son,-1,sizeof son); } //树状数组or线段树or其他 struct node{ int l,r; int min,max; int laz; }; struct node tree[maxn*3]; void PushUp(int rt){ tree[rt].max=max(tree[rt<<1].max,tree[rt<<1|1].max); tree[rt].min=min(tree[rt<<1].min,tree[rt<<1|1].min); } void PushDown(int rt){ int t; if(tree[rt].l==tree[rt].r) return ; if(tree[rt].laz){ tree[rt<<1].laz+=tree[rt].laz; tree[rt<<1].laz%=2; tree[rt<<1|1].laz+=tree[rt].laz; tree[rt<<1|1].laz%=2; tree[rt].laz=0; t=tree[rt<<1].max; tree[rt<<1].max=-tree[rt<<1].min; tree[rt<<1].min=-t; t=tree[rt<<1|1].max; tree[rt<<1|1].max=-tree[rt<<1|1].min; tree[rt<<1|1].min=-t; } } void build(int l,int r,int rt){ tree[rt].l=l; tree[rt].r=r; tree[rt].max=0; tree[rt].min=0; tree[rt].laz=0; if(l==r){ return ; } int m=(tree[rt].l+tree[rt].r)>>1; build(lson); build(rson); PushUp(rt); } void update(int p,int add,int rt){ if(tree[rt].l==tree[rt].r && tree[rt].l==p){ tree[rt].max=add; tree[rt].min=add; tree[rt].laz=0; return ; } PushDown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(p<=m) update(p,add,rt<<1); else update(p,add,rt<<1|1); PushUp(rt); } void update2(int L,int R,int rt){ if(L<=tree[rt].l && tree[rt].r<=R){ int t=tree[rt].max; tree[rt].max=-tree[rt].min; tree[rt].min=-t; tree[rt].laz+=1; tree[rt].laz%=2; return ; } PushDown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(L<=m) update2(L,R,rt<<1); if(R>m) update2(L,R,rt<<1|1); PushUp(rt); } int query_max(int L,int R,int rt){ if(L<=tree[rt].l && tree[rt].r<=R){ return tree[rt].max; } PushDown(rt); int m=(tree[rt].l+tree[rt].r)>>1; int ret=-inf; if(L<=m) ret=max(ret,query_max(L,R,rt<<1)); if(R>m) ret=max(ret,query_max(L,R,rt<<1|1)); PushUp(rt); return ret; } int find_max(int u,int v){ int f1,f2,ans=-inf; f1=top[u]; f2=top[v]; while(f1!=f2){ //始终f1的深度比f2要大。深度大先更新 if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } ans=max(ans,query_max(stree[f1],stree[u],1)); u=fa[f1]; f1=top[u]; } if(u==v) return ans; if(deep[u]>deep[v]) swap(u,v); ans=max(ans,query_max(stree[son[u]],stree[v],1)); return ans; } void change(int u,int v){ int f1,f2; f1=top[u]; f2=top[v]; while(f1!=f2){ //始终f1的深度比f2要大。深度大先更新 if(deep[f1]<deep[f2]){ swap(f1,f2); swap(u,v); } update2(stree[f1],stree[u],1); u=fa[f1]; f1=top[u]; } if(u==v) return ; if(deep[u]>deep[v]) swap(u,v); update2(stree[son[u]],stree[v],1); return ; } int e[maxn][5]; int main() { int t,x,y; int q,i; scanf("%d",&t); while(t--){ init(); scanf("%d",&n); for(i=0;i<n-1;i++){ scanf("%d %d %d",&e[i][0],&e[i][1],&e[i][2]); addedge(e[i][0],e[i][1]); addedge(e[i][1],e[i][0]); } dfs1(1,0,0);//根的deep是0.father从0开始。 getpos(1,1); build(0,pos-1,1); for(i=0;i<n-1;i++){ if(deep[e[i][0]]>deep[e[i][1]]) swap(e[i][0],e[i][1]); update(stree[e[i][1]],e[i][2],1); } char op[10]; while(1){ int a,b; scanf("%s",op); if(op[0]=='D') break; scanf("%d %d",&a,&b); if(op[0]=='Q') printf("%d\n",find_max(a,b)); else if(op[0]=='C') update(stree[e[a-1][1]],b,1); else change(a,b); } } return 0; } /* 10 7 1 2 1 1 3 2 3 4 3 3 5 4 5 6 5 5 7 6 NEGATE 1 3 QUERY 1 4 NEGATE 2 4 CHANGE 4 40 QUERY 4 5 NEGATE 2 7 QUERY 2 7 QUERY 3 5 CHANGE 4 30 NEGATE 2 7 QUERY 4 7 QUERY 4 5 QUERY 2 7 DONE 10 6 1 2 1 2 5 2 2 6 3 1 3 4 3 4 5 QUERY 4 5 CHANGE 1 3 QUERY 4 5 */
相关文章推荐
- 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 树链剖分
- Tree - POJ 3237 树链刨分
- POJ 题目3237 Tree(Link Cut Tree边权变相反数,求两点最大值)
- poj 3237 tree 树链剖分模板
- POJ 3237 Tree 树链剖分
- POJ 3237 树链剖分+线段树维护
- POJ 3237 Tree (树链剖分 路径更新)
- POJ - 3237 Tree (树链剖分+线段树+区间修改)
- POJ - 3237 Tree(树链剖分)
- poj 3237 Tree(树链剖分)
- poj 3237 -- Tree