您的位置:首页 > 其它

bzoj 1036: [ZJOI2008]树的统计Count 树链剖分+线段树

2017-12-22 20:25 519 查看

题目大意:

给你一颗树,每个点有权值,要你求出一个点到另一个点路径的最大权值,或者是权值和,还要支持修改权值的问题。

思路:

树链剖分的模板题。树链剖分大概就是把书上的链给按一定方法拆开,然后每一段去一个hash值,放入线段树中去维护他的区间值。

这里有一个大佬的博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html

程序:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#define inf 0x7fffffff
#define maxn 30005
#define maxm 60005
using namespace std;
int pos[maxn],top[maxn],fa[maxn],size[maxn],son[maxn],dep[maxn],a[maxn],last[maxn];
int n,cnt,sz;
struct data{int w,next;}e[maxm];
struct tree{int l,r,mx,sum;}t[100001];

void add(int u,int v){
e[++cnt].next=last[u]; e[cnt].w=v; last[u]=cnt;
e[++cnt].next=last[v]; e[cnt].w=u; last[v]=cnt;
}

void init(){
int u,v;
scanf("%d",&n);
for (int i=1;i<=n-1;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
}

void dfs1(int x){
size[x]=1;
for (int i=last[x];i;i=e[i].next){
if (fa[x]==e[i].w) continue;
fa[e[i].w]=x;
dep[e[i].w]=dep[x]+1;
dfs1(e[i].w);
size[x]+=size[e[i].w];
}
}

void dfs2(int x,int chain){
int k=0;
sz++;
pos[x]=sz;
top[x]=chain;
for (int i=last[x];i;i=e[i].next){
if (fa[x]!=e[i].w&&size[e[i].w]>size[k]) k=e[i].w;
}
if (k==0) return;
dfs2(k,chain);
for (int i=last[x];i;i=e[i].next){
if (e[i].w!=fa[x]&&e[i].w!=k) dfs2(e[i].w,e[i].w);
}
}

void build(int d,int l,int r){
t[d].l=l;
t[d].r=r;
if (l==r) return;
int mid=(l+r)/2;
build(d*2,l,mid);
build(d*2+1,mid+1,r);
}

void change(int d,int x,int y){
if (t[d].l==t[d].r) {
t[d].sum=t[d].mx=y;
return;
}
int mid=(t[d].l+t[d].r)/2;
if (x<=mid) change(d*2,x,y);
else change(d*2+1,x,y);
t[d].sum=t[d*2].sum+t[d*2+1].sum;
t[d].mx=max(t[d*2].mx,t[d*2+1].mx);
}

int querymax(int d,int x,int y){
if (t[d].l==x&&t[d].r==y) return t[d].mx;
int mid=(t[d].l+t[d].r)/2;
if (y<=mid) return querymax(d*2,x,y);
else if (x>mid) return querymax(d*2+1,x,y);
else return max(querymax(d*2,x,mid),querymax(d*2+1,mid+1,y));
}

int solvemax(int x,int y){
int mx=-inf;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
mx=max(mx,querymax(1,pos[top[x]],pos[x]));
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
mx=max(mx,querymax(1,pos[x],pos[y]));
return mx;
}

int querysum(int d,int x,int y){
if (t[d].l==x&&t[d].r==y) return t[d].sum;
int mid=(t[d].l+t[d].r)/2;
if (y<=mid) return querysum(d*2,x,y);
else if (x>mid) return querysum(d*2+1,x,y);
else return querysum(d*2,x,mid)+querysum(d*2+1,mid+1,y);

}

int solvesum(int x, int y){
int sum=0;
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
sum+=querysum(1,pos[top[x]],pos[x]);
x=fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
sum+=querysum(1,pos[x],pos[y]);
return sum;
}

int solve()
{
build(1,1,n);
for (int i=1;i<=n;i++)
change(1,pos[i],a[i]);
int q;
scanf("%d",&q);
char ch[10]; int x,y;
for (int i=1;i<=q;i++){
scanf("%s%d%d",ch,&x,&y);
if (ch[0]=='C') change(1,pos[x],y);
else {
if (ch[1]=='M') printf("%d\n",solvemax(x,y));
else printf("%d\n",solvesum(x,y));
}
}
}
int main(){
init();
dfs1(1);
dfs2(1,1);

solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  何嘉阳