POJ 3237 Tree 树链剖分(路径剖分
2016-05-16 23:28
267 查看
题意:有n-1条路,形成一棵树,每条路有一个权值,有三种操作
1.CHANGE i v 把第i条路权值改为v
2.NEGATE a b把路径a~b的权值全部取反
3.QUERY a b 查询路径a~b的权值的最大值
思路:
有区别有点剖分的是,我们用deep比较大的点来保存这条边,在进行链合并的时候注意在LCA的地方不能去LCA的值,因为LCA的值是LCA-deep更小的边,并不是这条路径上的边
1.CHANGE i v 把第i条路权值改为v
2.NEGATE a b把路径a~b的权值全部取反
3.QUERY a b 查询路径a~b的权值的最大值
思路:
有区别有点剖分的是,我们用deep比较大的点来保存这条边,在进行链合并的时候注意在LCA的地方不能去LCA的值,因为LCA的值是LCA-deep更小的边,并不是这条路径上的边
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<queue> #include<stack> #include<string> #include<vector> #include<map> #include<set> using namespace std; #define lowbit(x) (x&(-x)) typedef long long LL; #define maxn 10005 const int inf=1000000000; int S[20]; int max(int a,int b) { if(a>b) return a; return b; } int min(int a,int b) { if(a>b) return b; return a; } struct node { int next,to,v; }e[maxn*2]; int h[maxn],tot; void add_edge(int a,int b,int c) { e[++tot].next=h[a]; e[tot].to=b; e[tot].v=c; h[a]=tot; } //graph************************** int ft[maxn][14]; int fa[maxn],deep[maxn],son[maxn],siz[maxn]; void dfs1(int u,int pre,int dep) { fa[u]=pre; deep[u]=dep; siz[u]=1; for(int i=1;i<14;++i) { if(dep<S[i]) break; ft[u][i]=ft[ft[u][i-1]][i-1]; } for(int i=h[u];~i;i=e[i].next) { int v=e[i].to; if(v!=pre) { ft[v][0]=u; dfs1(v,u,dep+1); siz[u]+=siz[v]; if(son[u]==-1||siz[son[u]]<siz[v]) son[u]=v; } } } int top[maxn],tid[maxn],Rank[maxn]; int tim; void dfs2(int u,int tp) { top[u]=tp; tid[u]=++tim; Rank[tim]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=h[u];~i;i=e[i].next) { int v=e[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); int t=deep[x]-deep[y]; for(int i=0;i<14;++i) if(t&S[i]) x=ft[x][i]; for(int i=13;i>=0;--i) if(ft[x][i]!=ft[y][i]) { x=ft[x][i]; y=ft[y][i]; } if(x==y) return x; return ft[x][0]; } //树剖*************************** struct Segment { int Max,Min,lazy; }tree[maxn*4]; void Push_up(int rt) { tree[rt].Max=max(tree[rt*2].Max,tree[rt*2+1].Max); tree[rt].Min=min(tree[rt*2].Min,tree[rt*2+1].Min); } void fun(int rt) { tree[rt].Min*=-1; tree[rt].Max*=-1; swap(tree[rt].Min,tree[rt].Max); tree[rt].lazy^=1; } void Push_down(int rt) { if(tree[rt].lazy) { fun(rt*2);fun(rt*2+1); tree[rt].lazy=0; } } void build(int l,int r,int rt) { tree[rt].lazy=0; tree[rt].Max=-inf; tree[rt].Min=inf; if(l==r) return ; int mid=(l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); } void Insert(int pos,int l,int r,int rt,int c) { if(l==r) { tree[rt].Max=tree[rt].Min=c; return ; } Push_down(rt); int mid=(l+r)/2; if(pos<=mid) Insert(pos,l,mid,rt*2,c); else Insert(pos,mid+1,r,rt*2+1,c); Push_up(rt); } void query(int left,int right,int l,int r,int rt,int &Max) { if(left<=l&&r<=right) { Max=max(tree[rt].Max,Max); return ; } Push_down(rt); int mid=(l+r)/2; if(left<=mid) query(left,right,l,mid,rt*2,Max); if(right>mid) query(left,right,mid+1,r,rt*2+1,Max); Push_up(rt); } void update(int left,int right,int l,int r,int rt) { if(left<=l&&r<=right) { fun(rt); return ; } Push_down(rt); int mid=(l+r)/2; if(left<=mid) update(left,right,l,mid,rt*2); if(right>mid) update(left,right,mid+1,r,rt*2+1); Push_up(rt); } //Segment************************ int n; void Change(int x,int t) { while(top[x]!=top[t]) { update(tid[top[x]],tid[x],1,n,1); x=fa[top[x]]; } update(tid[t],tid[x],1,n,1); } int Solve(int x,int t) { int Max=-inf; while(top[x]!=top[t]) { query(tid[top[x]],tid[x],1,n,1,Max); x=fa[top[x]]; } if(x==t) return Max; query(tid[son[t]],tid[x],1,n,1,Max); return Max; } void init() { tot=tim=0; memset(h,-1,sizeof(h)); memset(son,-1,sizeof(son)); memset(fa,0,sizeof(fa)); } struct AAA { int u,v,c; }A[maxn]; int main() { int T; S[0]=1; for(int i=1;i<15;++i) S[i]=S[i-1]*2; scanf("%d",&T); while(T--) { init(); scanf("%d",&n); for(int i=1;i<n;++i) { int u,v,c; scanf("%d%d%d",&u,&v,&c); add_edge(u,v,c); add_edge(v,u,c); A[i].u=u;A[i].v=v; A[i].c=c; } dfs1(1,1,0); dfs2(1,1); build(1,n,1); for(int i=1;i<n;++i) { int x; if(deep[A[i].u]<deep[A[i].v]) swap(A[i].u,A[i].v); x=A[i].u; Insert(tid[x],1,n,1,A[i].c); } while(1) { char str[10]; scanf("%s",str); int x,y; if(str[0]=='D') break; scanf("%d%d",&x,&y); if(str[0]=='Q') { int t=lca(x,y); int Max=Solve(x,t); Max=max(Solve(y,t),Max); printf("%d\n",Max); } else if(str[0]=='N') { int t=lca(x,y); Change(x,t); Change(y,t); } else { int t=A[x].u; Insert(tid[t],1,n,1,y); } } } return 0; }
相关文章推荐
- hdu-5405
- hybz1036 树的统计Count
- poj3237 Tree
- hybz2243 染色
- 【bzoj1036】【树链剖分】【ZJOI2008】树的统计Count
- BZOJ 2243 染色 [树链剖分]
- BZOJ 4326 运输计划 transport 【NOIP 2015】【树链剖分】
- 4034: [HAOI2015]T2 (树链剖分)
- SPOJ 375. Query on a tree (基于边的树链剖分)
- 1036: [ZJOI2008]树的统计Count (基于点的树链剖分)
- Poj2831 树链剖分||次小生成树
- Poj2746-Housewife Wind 树链剖分入门(边权)
- 树链剖分(详解)
- HDU3966(树链剖分)
- 树链剖分简单入门
- poj 3237 树链剖分+线段树
- poj 3237 树链剖分
- SPOJ QTREE 1-3题解
- bzoj 1036 [ZJOI2008]树的统计Count(树链剖分入门系列)
- 【HAOI2015】【BZOJ4034】树上操作T2