POJ 3237 Tree 树链剖分(路径剖分
来源:互联网 发布:通达信软件使用说明书 编辑:程序博客网 时间:2024/05/22 06:13
题意:有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更小的边,并不是这条路径上的边
#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 10005const 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;}
0 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 3237Tree 树链剖分
- POJ 3237 Tree 树链剖分
- POJ-3237Tree(树链剖分)
- poj 2983 差分路径+SPFA
- 利用 autoconf 和 automake 自动生成Makefile
- 《算法》第四版《Algorithms》4th Edition 学习环境搭建
- Android开发之xml的解析
- 《Wireshark 网络分析就这么简单》学习笔记
- HYSBZ - 2152
- POJ 3237 Tree 树链剖分(路径剖分
- Simple Tree Traverse(遍历)
- 数据库命令大全
- 程序员都应该懂点心理学
- 利用组合控件实现布局文件抽取复用--自定义view属性抽取
- getlin与get的区别
- java正则匹配及替换的一点思考
- 风花雪月
- 七、二叉排序树--(1)什么是二叉排序树