poj 3237 Tree 树链剖分
2015-09-19 23:58
127 查看
// poj 3237 Tree 树链剖分 // // 解题思路: // // 树链剖分,维护一个最大值和一个最小值, // 区间更新,laz标记.单点更新,去掉叶子节点的laz // 标记.边权改为离根节点较远的点的点权.求lca // 的方式进行区间更新.注意线段树的操作以及push_up() // push_down()的操作.写了很久,感悟颇多,继续加油吧~~~ #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #define cls(x,a) memset(x,a,sizeof(x)) using namespace std; const int MAXN = 10008; const int INF = 0x7fffffff; int n; int num; int id; int idx[MAXN]; // 树上节点在线段树中的编号 int son[MAXN]; // 重儿子 int siz[MAXN]; // 以该节点为根的子树的节点数 int dep[MAXN]; // 节点的深度 int top[MAXN]; // 链的开头 int rk[MAXN]; // 与idx互逆的 int father[MAXN]; // 父节点 int head[MAXN]; int val[MAXN]; struct adj{ int to; int next; adj(){ } adj(int a,int b):to(a),next(b){ } }edges[MAXN<<1]; struct node { int u; int v; int w; node(){ } node(int u,int v,int w):u(u),v(v),w(w){ } }e[MAXN]; void add_edge(int u,int v){ edges[num] = adj(v,head[u]); head[u] = num++; } void dfs(int u,int fa,int d){ dep[u] = d; father[u] =fa; son[u] = 0; siz[u] = 1; for (int i = head[u]; i + 1; i = edges[i].next){ int v = edges[i].to; if (v == fa) continue; dfs(v,u,d+1); siz[u] += siz[v]; if (siz[son[u]] < siz[v]) son[u] = v; } } void dfs(int u,int tp){ top[u] = tp; idx[u] = id++; rk[idx[u]] = u; if (son[u]) dfs(son[u],tp); for (int i = head[u] ;i + 1 ;i = edges[i].next){ int v = edges[i].to; if (v == father[u] || v == son[u]) continue; dfs(v,v); } } void input(){ id = 1; num = 0; cls(idx,0); cls(father,0); cls(son,0); cls(head,-1); scanf("%d",&n); for (int i = 1;i < n;i ++){ int u,v,w; scanf("%d%d%d",&u,&v,&w); e[i] = node(u,v,w); add_edge(u,v); add_edge(v,u); } } #define lson(x) (x<<1) // 线段树部分 #define rson(x) (x<<1|1) int vmax[MAXN<<2]; int vmin[MAXN<<2]; int laz[MAXN<<2]; int ql,qr; int delta; inline void update_node(int ro){ vmax[ro] *= -1; vmin[ro] *= -1; swap(vmin[ro],vmax[ro]); } inline void push_up(int ro){ vmax[ro] = max(vmax[lson(ro)],vmax[rson(ro)]); vmin[ro] = min(vmin[lson(ro)],vmin[rson(ro)]); } inline void push_down(int ro,int L,int R){ if (L == R) return; if (laz[ro]){ laz[lson(ro)] ^= 1; laz[rson(ro)] ^= 1; update_node(lson(ro)); update_node(rson(ro)); laz[ro] = 0; } } void build(int ro,int L,int R){ laz[ro] = 0; if (L == R){ vmax[ro] = val[L]; vmin[ro] = val[L]; return ; } int M = (L + R) >> 1; build(lson(ro),L,M); build(rson(ro),M+1,R); push_up(ro); } void n_update(int ro,int L,int R){ if (ql<= L && R <= qr){ laz[ro] ^= 1; update_node(ro); return ; } push_down(ro,L,R); int M = (L + R) >> 1; if (ql <= M ) n_update(lson(ro),L,M); if (M < qr) n_update(rson(ro),M+1,R); push_up(ro); } void c_update(int ro,int L,int R){ if (L == R){ vmax[ro] = delta; vmin[ro] = delta; laz[ro] = 0; return ; } push_down(ro,L,R); int M = (L + R) >> 1; if (ql <= M) c_update(lson(ro),L,M); else c_update(rson(ro),M+1,R); push_up(ro); } int query(int ro,int L,int R){ if (ql <= L && R <= qr){ return vmax[ro]; } push_down(ro,L,R); int M = (L + R) >> 1; int ans = -INF; if (ql <= M) ans = max(ans,query(lson(ro),L,M)); if (M < qr) ans = max(ans,query(rson(ro),M+1,R)); return ans; } void split(){ dfs(1,0,0); dfs(1,1); for (int i = 1;i < n;i ++){ if (dep[e[i].u] < dep[e[i].v]) swap(e[i].u,e[i].v); val[idx[e[i].u]] = e[i].w; } build(1,1,n); } void Negate(int u,int v){ int p = top[u], q = top[v]; int ans = INF; while(p!=q){ if (dep[p] < dep[q]){ swap(p,q); swap(u,v); } ql = idx[p]; qr = idx[u]; n_update(1,1,n); u = father[p]; p = top[u]; } if (u == v) return; if (dep[u] > dep[v]) swap(u,v); ql = idx[son[u]]; qr = idx[v]; n_update(1,1,n); } int get_max(int u,int v){ int p = top[u], q = top[v]; int ans = -INF; while(p!=q){ if (dep[p] < dep[q]){ swap(p,q); swap(u,v); } ql = idx[p]; qr = idx[u]; ans = max(ans,query(1,1,n)); u = father[p]; p = top[u]; } if (u == v) return ans; if (dep[u] > dep[v]) swap(u,v); ql = idx[son[u]]; qr = idx[v]; ans = max(ans,query(1,1,n)); return ans; } void solve(){ char s[20]; while(1){ scanf("%s",s); if (s[0] == 'D') break; else if (s[0] == 'Q'){ int u,v; scanf("%d%d",&u,&v); printf("%d\n",get_max(u,v)); }else if (s[0] == 'C'){ int i,v; scanf("%d%d",&i,&v); ql = idx[e[i].u]; delta = v; c_update(1,1,n); }else { int u,v; scanf("%d%d",&u,&v); Negate(u,v); } } } int main(){ int t; //freopen("1.txt","r",stdin); scanf("%d",&t); while(t--){ input(); split(); solve(); } return 0; }
相关文章推荐
- git的学习
- 日期类
- openwrt 按键处理
- 百度,得之我幸,失之我命!
- 在树莓派上安装和使用GPIO
- 机器人系统常用仿真软件介绍和效果
- PHP实现http与https转化
- <android>MeasureSpec的彻底讲解
- session的生命周期
- iOS开发零基础教程之开发证书以及打包问题
- Python中的高阶函数与匿名函数
- ElasticSearch基础杂烩-配置-索引-优化
- 在windows下的nodejs的环境配置
- tomcat源码分析 StandardServer初始化过程
- android中上下文Context的意义
- elasticsearch java调用实例
- 技术团队代码管理和部署
- 第一次博客
- JS eval()函数处理json字符串
- CentOS 安装tomcat 7