POJ 3237 树链剖分
来源:互联网 发布:ubuntu 查看重启日志 编辑:程序博客网 时间:2024/06/10 12:27
这个知识点学了4天,有两天的时间都在调试这个代码,发现自己写的还是少,发现了好多的bug,和很神奇的事情发生,比如写个递归忘了写return,还有好多。
树链剖分:按照某个规则对树进行划分,而现在这个是按照轻重链对树进行划分。
概念:
重儿子:对于结点v来说他的儿子里面孙子最多的一个。
重链 :v与他的重儿子的连边。
top[] :与v在同一重链上的根节点。
ti[] :当前边在线椴树中的位置。
dep[] :结点的深度。
siz[] : 结点的儿子个数。
father[]:结点的父亲。
son[] : 结点的儿子。
流程:按照这种划分把边分别都安排了顺序,那么在改变边值的时候,就可以用到线段树的知识了。
复杂度分析:这个不是很理解,不过可以和线段树那样的复杂度解决这个问题,轻链直接更新,重链线段树维护
概念:
重儿子:对于结点v来说他的儿子里面孙子最多的一个。
重链 :v与他的重儿子的连边。
top[] :与v在同一重链上的根节点。
ti[] :当前边在线椴树中的位置。
dep[] :结点的深度。
siz[] : 结点的儿子个数。
father[]:结点的父亲。
son[] : 结点的儿子。
流程:按照这种划分把边分别都安排了顺序,那么在改变边值的时候,就可以用到线段树的知识了。
复杂度分析:这个不是很理解,不过可以和线段树那样的复杂度解决这个问题,轻链直接更新,重链线段树维护
#include<iostream>#include<cstring>#include<algorithm>#define lson id << 1#define rson id << 1|1#include<cstdio>using namespace std;const int M = 10008;int father[M],dep[M],top[M],siz[M],ti[M],son[M];int idx,tp = 0;const int Inf = 0x3ffff;struct line_tree{ int l,r,Max,Min,mark; int mid(){ return (l+r)/2; }}node[M*100];struct { int head;}H[M];struct{ int v,next;}E[M*100];void add(int u,int v){ E[tp].v = v; E[tp].next = H[u].head; H[u].head = tp++;}void init(){ memset(E,-1,sizeof(E)); memset(H,-1,sizeof(H)); tp = 0;idx = 0; memset(son,0,sizeof(son)); memset(top,0,sizeof(top));}void dfs_1(int u,int fa){ son[u] = 0;siz[u] = 1;dep[u] = dep[fa] + 1; father[u] = fa; for(int i=H[u].head;i!=-1;i=E[i].next){ int v = E[i].v; if(v == fa)continue; dfs_1(v,u); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; }}void dfs_2(int u,int fa){ top[u] = fa; ti[u] = idx++; if(son[u])dfs_2(son[u],fa); for(int i=H[u].head;i!=-1;i=E[i].next){ int v = E[i].v; if(v == father[u]||v == son[u])continue; dfs_2(v,v); }}/* 线段树*/void build_tree(int id,int l,int r){ node[id].l = l;node[id].r = r;node[id].mark = 0; node[id].Max = node[id].Min = 0; if(l == r)return; int mid = node[id].mid(); build_tree(lson,l,mid); build_tree(rson,mid+1,r);}void push_down(int id){ if(node[id].l == node[id].r)return; if(node[id].mark){ node[lson].Max = -node[lson].Max; node[lson].Min = -node[lson].Min; swap(node[lson].Max,node[lson].Min); node[rson].Max = -node[rson].Max; // 妈的,大意了调试了1天 node[rson].Min = -node[rson].Min; swap(node[rson].Max,node[rson].Min); node[lson].mark ^= 1; node[rson].mark ^= 1; node[id].mark = 0; }}void push_up(int id){ node[id].Max = max(node[lson].Max,node[rson].Max); node[id].Min = min(node[lson].Min,node[rson].Min);}bool flag = false;void update(int id,int k,int w){ if(node[id].l == k&&node[id].r == k){ node[id].Max = node[id].Min = w; return; } push_down(id); int mid = node[id].mid(); if(k <= mid)update(lson,k,w); else update(rson,k,w); push_up(id);}void nede(int id,int l,int r){ if(node[id].l == l&&node[id].r == r){ node[id].Max = -node[id].Max; node[id].Min = -node[id].Min; swap(node[id].Max,node[id].Min); node[id].mark ^= 1; return; } push_down(id); int mid = node[id].mid(); if(r <=mid)nede(lson,l,r); else if(l > mid)nede(rson,l,r); else{ nede(lson,l,mid); nede(rson,mid+1,r); } push_up(id);}int ans = 0;int query(int id,int l,int r){ if( node[id].l == l&&node[id].r == r)return node[id].Max; push_down(id); int mid= node[id].mid(); if(r <=mid)return query(lson,l,r); else if(l > mid)return query(rson,l,r); else return max( query(lson,l,mid),query(rson,mid+1,r)); push_up(id);}int findMax(int u,int v){ int f1 = top[u]; int f2 = top[v]; int mmax = -Inf; while(f1 !=f2){ if(dep[f1] < dep[f2]){ swap(f1,f2); swap(u,v); } mmax = max(mmax,query(1,ti[f1],ti[u])); u = father[f1];f1 = top[u]; } if(u == v)return mmax; if(dep[u] > dep[v])swap(u,v); mmax = max(mmax,query(1,ti[son[u]],ti[v])); return mmax;}void negat(int u,int v){ int f1 = top[u]; int f2 = top[v]; while(f1 != f2){ if(dep[f1] < dep[f2]){ swap(f1,f2); swap(u,v); } nede(1,ti[f1],ti[u]); u = father[f1];f1 = top[u]; } if(u == v)return; if(dep[u] > dep[v])swap(u,v); nede(1,ti[son[u]],ti[v]);}int e[M][3];int main(){ int n,m; int T; scanf("%d",&T); while(T--){ init(); scanf("%d",&n); for(int i=0;i<n-1;i++){ scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]); add(e[i][0],e[i][1]); add(e[i][1],e[i][0]); } dfs_1(1,1); dfs_2(1,1); build_tree(1,1,idx-1); for(int i=0;i<n-1;i++){ if(dep[e[i][0]] > dep[e[i][1]]) swap(e[i][0],e[i][1]); update(1,ti[e[i][1]],e[i][2]); } char str[100]; int u,v; while(scanf("%s",str) == 1){ if(str[0] == 'D')break; scanf("%d%d",&u,&v); // cout <<"ti-->" <<ti[u] << "tiv-->"<<ti[v] <<endl; if(str[0] == 'Q') printf("%d\n",findMax(u,v)); else if(str[0] == 'C') update(1,ti[e[u-1][1]],v); else negat(u,v); } }}
0 0
- POJ 3237树链剖分
- POJ 3237 Tree 树链剖分
- 【POJ】3237 Tree 树链剖分
- POJ 3237 Tree 树链剖分
- POJ 3237 树链剖分
- 【树链剖分】 POJ 3237 Tree
- poj 3237 Tree(树链剖分)
- POJ 3237 Tree (树链剖分)
- POJ 3237 Tree 树链剖分
- poj-3237(树链剖分)
- POJ 3237 Tree 树链剖分
- POJ 3237(树链剖分)
- poj 3237 Tree 树链剖分
- poj 3237 Tree 树链剖分
- POJ 3237 - Tree(树链剖分)
- poj 3237 树链剖分
- poj 3237 Tree 树链剖分
- poj 3237(树链剖分)
- hdu5059
- JAVA本地方法 native method
- ORACLE打开和关闭数据--基础
- 工作周报三
- 【BZOJ】【P1951】【Sdoi2010】【古代猪文】【题解】【数论】
- POJ 3237 树链剖分
- [设计模式01]-单例模式
- Vuforia SDK---- Vuforia识别类型介绍
- CF475D. CGCDSSQ
- 扩展cxLookupComboBox,使其支持多列查询的cxLookupComboBoxEx
- JNI学习之一:怪异的JNI报错:Caused by: java.lang.UnsatisfiedLinkError
- java实现冒泡排序算法
- 一种简单实用的双向电平转换电路(非常实用!)3.3V--5V
- UVA - 10148 Advertisement