Spoj 375 QTREE1 树链剖分裸题
来源:互联网 发布:java定时器执行一次 编辑:程序博客网 时间:2024/05/22 08:02
题目链接:http://www.spoj.com/problems/QTREE/
题意:
T个测试案例
n个点的树
下面n-1条边和边权
change u v 把第u-th给出的边 的边权改为v
query 询问路径 [u, v] 间最大的边权
#include<stdio.h>#include<iostream>#include<string.h>#include<math.h>#include<algorithm>#define N 10010#define L(x) (x<<1)#define R(x) (x<<1|1)#define Mid(x,y) ((x+y)>>1)using namespace std;struct Edge{int from, to, nex;}edge[N<<1];int head[N], edgenum;void add(int u, int v){Edge E={u, v, head[u]}; edge[edgenum] = E;head[u] = edgenum++;}int fa[N], siz[N], son[N], w[N], p[N], dep[N], tree_id;int fp[N];//和p数组相反//给每条边编号 边(u, v),设dep[u]<dep[v](v在下面) 用v来表示边的编号//w[v] 表示v所在的父边 在线段树中的位置void dfs(int u, int father, int deep){son[u] = 0; fa[u] = father; siz[u] = 1; dep[u] = deep;for(int i = head[u]; ~i; i = edge[i].nex){int v = edge[i].to;if(v == father)continue;dfs(v, u, deep+1);siz[u] += siz[v];if(siz[v] > siz[ son[u] ])son[u] = v;}}void Have_p(int u, int father){w[u] = ++tree_id; p[u] = father;if(son[u])Have_p(son[u], father);else return;for(int i = head[u]; ~i; i = edge[i].nex){int v = edge[i].to;if(v != fa[u] && v != son[u])Have_p(v, v);}}struct node{int l, r;int Max;}tree[N*4];void build(int l, int r, int id){tree[id].l = l, tree[id].r = r;tree[id].Max = 0;if(l == r)return ;int mid = Mid(l,r);build(l, mid, L(id));build(mid+1, r, R(id));}void updata(int pos, int val, int id){if(tree[id].l == tree[id].r){tree[id].Max = val;return ;}int mid = Mid(tree[id].l, tree[id].r);if(pos <= mid)updata(pos, val, L(id));elseupdata(pos, val, R(id));tree[id].Max = max(tree[L(id)].Max, tree[R(id)].Max);}int query(int l, int r, int id){if(l == tree[id].l && tree[id].r == r)return tree[id].Max;int mid = Mid(tree[id].l, tree[id].r);if(r<=mid)return query(l, r, L(id));else if(mid<l)return query(l, r, R(id));elsereturn max(query(l, mid, L(id)), query(mid+1, r, R(id)));}int find(int u, int v){int f1 = p[u], f2 = p[v];int tmp = 0;while(f1 != f2){if(dep[f1] < dep[f2])swap(f1, f2), swap(u, v);tmp = max(tmp, query(w[f1], w[u], 1));u = fa[f1], f1 = p[u];}if(u == v)return tmp;if(dep[u] > dep[v])swap(u, v);return max(tmp, query(w[son[u]], w[v], 1));}int n;int D[N][3];void init(){memset(head, -1, sizeof(head)); edgenum = 0;memset(son, 0, sizeof(son));//这个的初始化tree_id = 0;}int main(){int T;scanf("%d",&T);int i, u, v, d;char s[10];while(T--){scanf("%d",&n);init();for(i=1;i<n;i++){scanf("%d %d %d", &u,&v,&d);D[i][0] = u, D[i][1] = v, D[i][2] = d;add(u, v), add(v, u);}dfs(1, 1, 0);Have_p(1, 1);build(1, n, 1);for(i=1;i<n;i++){//int u = D[i][0], v = D[i][1], d = D[i][2];//if(dep[u]>dep[v]) swap(u, v)因为 w[v] 是表示父边,显然是深度大的v才能表示父边if(dep[ D[i][0] ] > dep[ D[i][1] ])swap(D[i][0], D[i][1]);updata(w[ D[i][1] ], D[i][2], 1);}while(scanf("%s",s)){ if(s[0] == 'D')break;scanf("%d %d", &u, &v);if(s[0] == 'C')updata(w[D[u][1]], v, 1);elseprintf("%d\n", find(u,v));}}return 0;}
0 0
- Spoj 375 QTREE1 树链剖分裸题
- Qtree1
- spoj 375
- 【SPOJ】QTREE 1 树链剖分裸题
- spoj 375 (树链剖分)
- SPOJ 375 树链剖分
- 【转】SPOJ 375 树链剖分
- spoj 375 树链剖分模板
- SPOJ 375 树链剖分学习
- SPOJ 375 LCT学习
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- SPOJ 375 树链剖分
- 树链剖分模板(spoj 375)
- 树链剖分(SPOJ 375)
- SPOJ 375 QTREE
- LCT spoj 375 树链剖分
- vs2010编写C和解决窗口一闪而过的方法
- C++类的继承
- wrod中的公式字体
- 关于target...action中的一点体会
- 判断回文整型数
- Spoj 375 QTREE1 树链剖分裸题
- Codeforces Round #219 (Div. 2) D. Counting Rectangles is Fun
- Working Practice-先实现再改进
- 异常处理
- Ubuntu 出现apt-get: Package has no installation candidate问题
- 数字电视 frontend tuner demod
- SIO_KEEPALIVE_VALS 用户异常掉线检测
- 标准输入cin的返回值以及读入未知数目数据的问题
- 内联(inline)函数与虚函数(virtual)的讨论