HYSBZ 1036(树链剖分)

题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/E

题意:给定一棵树及树上的点权,要求三种操作:

1)CHANGE u t : 把结点u的权值改为t。

2)QMAX u v: 询问从点u到点v的路径上的节点的最大权值。

3)QSUM u v: 询问从点u到点v的路径上的节点的权值和

分析:树链剖分后就是线段树的单点修改,区间求和与区间求最值。。。

#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define mod 10007
#define inf 0x3f3f3f3f
#define N 100010
#define FILL(a,b) (memset(a,b,sizeof(a)))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
struct edge
{
int to,next;
edge(){}
edge(int to,int next):to(to),next(next){}
}e[N<<];
int head[N<<],tot;
int top[N];//top[v]表示v所在的重链的顶端节点
int fa[N];//父亲节点
int dep[N];//深度
int sz[N];//si[v]表示以v为根节点的子树的节点数
int son[N];//重儿子
int p[N];//p[v]表示v与其父亲节点的连边在线段树中的位置
int fp[N];//与p数组相反
int pos;//所有链构成的线段树总长度
int sum[N<<],mx[N<<],a[N];
void addedge(int u,int v)
{
e[tot]=edge(v,head[u]);
head[u]=tot++;
}
void init()
{
tot=;FILL(head,-);
pos=;FILL(son,-);
}
void dfs(int u,int f,int d)
{
dep[u]=d;sz[u]=;fa[u]=f;
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v==f)continue;
dfs(v,u,d+);
sz[u]+=sz[v];
if(son[u]==-||sz[son[u]]<sz[v])son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=++pos;
fp[pos]=u;
if(son[u]==-)return;
getpos(son[u],sp);
for(int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=fa[u])
{
getpos(v,v);
}
}
}
void Pushup(int rt)
{
int ls=rt<<,rs=ls|;
sum[rt]=sum[ls]+sum[rs];
mx[rt]=max(mx[ls],mx[rs]);
}
void build(int l,int r,int rt)
{
if(l==r)
{
mx[rt]=sum[rt]=a[fp[l]];
return;
}
int m=(l+r)>>;
build(lson);
build(rson);
Pushup(rt);
}
void update(int ps,int c,int l,int r,int rt)
{
if(l==r)
{
mx[rt]=sum[rt]=c;
return;
}
int m=(l+r)>>;
if(ps<=m)update(ps,c,lson);
else update(ps,c,rson);
Pushup(rt);
}
int querysum(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return sum[rt];
int m=(l+r)>>;
int res=;
if(L<=m)res+=querysum(L,R,lson);
if(R>m)res+=querysum(L,R,rson);
return res;
}
int querymax(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
return mx[rt];
int m=(l+r)>>;
int res=-inf;
if(L<=m)res=max(res,querymax(L,R,lson));
if(m<R)res=max(res,querymax(L,R,rson));
return res;
}
int lca(int u,int v,int flag)
{
int fu=top[u],fv=top[v],res;
if(flag)res=-inf;
else res=;
while(fu!=fv)
{
if(dep[fu]<dep[fv])
{
swap(fu,fv);
swap(u,v);
}
if(flag)res=max(res,querymax(p[fu],p[u],,pos,));
else res+=querysum(p[fu],p[u],,pos,);
u=fa[fu];fu=top[u];
}
if(dep[u]>dep[v])swap(u,v);
if(flag)res=max(res,querymax(p[u],p[v],,pos,));
else res+=querysum(p[u],p[v],,pos,);
return res;
}
int main()
{
int n,t,u,v,w;
char op[];
while(scanf("%d",&n)>)
{
init();
for(int i=;i<n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
for(int i=;i<=n;i++)scanf("%d",&a[i]);
dfs(,,);
getpos(,);
build(,pos,);
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
scanf("%d%d",&u,&v);
if(op[]=='S')
{
printf("%d\n",lca(u,v,));
}
else if(op[]=='M')
{
printf("%d\n",lca(u,v,));
}
else
{
update(p[u],v,,pos,);
}
}
}
}
上一篇:开始研究Ray tracing


下一篇:jQuery使用():Callbacks回调函数列表之异步编程(含源码分析)