您的位置:首页 > 产品设计 > UI/UE

spoj 375 QTREE - Query on a tree(树链剖分,边权)

2017-10-03 16:28 441 查看
边权的树链剖分,把边权都推到下边的点上,就是点权了,然后,根节点没有权值。

还是kuangbin大佬的模板。。。。

#include <bits/stdc++.h>
//每条边两个点,把每条边的权值放到深度较深的那个点上,根节点无权值,就是方个最小值
const int MAXN = 10010;
struct Edge
{
int to,next;
} edge[MAXN*2];
int head[MAXN],tot;
int top[MAXN];//top[v]表示v所在的重链的顶端节点
int fa[MAXN]; //父亲节点
int dep[MAXN];//深度
int num[MAXN];//num[v]表示以v为根的子树的节点数
int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[MAXN];//和p数组相反
int son[MAXN];//重儿子
int pos;
int e[MAXN][3];

void init()
{
tot = 0;
memset(head,-1,sizeof(head));
pos = 0;
memset(son,-1,sizeof(son));
}

void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}

void dfs1(int u, int pre, int d)
{
dep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre) continue;
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}

void getpos(int u, int sp)
{
top[u] = sp;
p[u] = pos++;
if(son[u] == -1) return;
getpos(son[u],sp);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v != son[u] && v != fa[u])
getpos(v,v);
}
}

struct Node
{
int l,r;
int Max;
}segTree[MAXN*3];

void build(int i, int l, int r)
{
segTree[i].l = l;
segTree[i].r = r;
segTree[i].Max = 0;
if(l == r) return;
int mid = (l+r) >> 1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}

void push_up(int i)
{
segTree[i].Max = std::max(segTree[i<<1].Max,segTree[(i<<1)|1].Max);
}

void update(int i, int k, int val)// 更新线段树的第k个值为val
{
if(segTree[i].l == k && segTree[i].r == k)
{
segTree[i].Max = val;
return;
}
int mid = (segTree[i].l + segTree[i].r) >> 1;
if(k <= mid) update(i<<1,k,val);
else update(i<<1|1,k,val);
push_up(i);
}

int query(int i, int l, int r)
{
if(segTree[i].l == l && segTree[i].r == r)
return segTree[i].Max;
int mid = (segTree[i].l + segTree[i].r) >> 1;
if(r <= mid) return query(i<<1, l, r);
else if(l > mid) return query(i<<1|1, l, r);
else return std::max(query(i<<1,l , mid), query(i<<1|1, mid+1, r));
}

int find(int u, int v)
{
int f1 = top[u], f2 = top[v];
int tmp = 0;
while(f1 != f2)
{
if(dep[f1] < dep[f2])
{
std::swap(f1,f2);
std::swap(u,v);
}
tmp = std::max(tmp,query(1,p[f1],p[u]));
u = fa[f1];
f1 = top[u];
}
if(u == v) return tmp;
if(dep[u] > dep[v]) std::swap(u,v);
//因为边权都被推到下边的点上了,所以u->v的边权最值,就是son[u]->v的点权值
return std::max(tmp,query(1,p[son[u]],p[v]));
}

int main()
{
int T;
int n;
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]);
addedge(e[i][0],e[i][1]);
addedge(e[i][1],e[i][0]);
}
dfs1(1,0,0);
getpos(1,1);
build(1,0,pos-1);
for(int i = 0; i < n-1; ++i)
{
if(dep[e[i][0]] > dep[e[i][1]])
std::swap(e[i][0],e[i][1]);
update(1,p[e[i][1]],e[i][2]);
}
char op[10];
int u,v;
while(scanf(" %s",op))
{
if(op[0] == 'D') break;
scanf("%d %d",&u,&v);
if(op[0] == 'Q') printf("%d\n",find(u,v));
else update(1,p[e[u-1][1]],v);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: