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
原创粉丝点击