您的位置:首页 > 其它

BZOJ 1036: [ZJOI2008]树的统计Count

2014-05-12 21:01 405 查看
题目地址:http :// www . lydsy . com / JudgeOnline / problem . php ? id = 1036

题目大意:给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。

算法讨论:树链剖分模板题。

Code:

#include <cstdio>
#include <algorithm>

#define N 30000
#define oo 0x7f7f7f7f

using namespace std;

int n,x,y,tot,q,mm,w[N+10],next[N*2+10],son[N+10],ed[N*2+10],fa[N+10],deep[N+10],size[N+10],heavy[N+10],tree1[N*4+10],tree2[N*4+10],head[N+10],id[N+10],num[N+10];
bool vis[N+10];
char s[10];

void add(int x,int y){
next[++mm]=son[x];
son[x]=mm;
ed[mm]=y;
}

void dfs1(int x){
vis[x]=1;
size[x]=1;
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (!vis[y]){
fa[y]=x;
deep[y]=deep[x]+1;
dfs1(y);
size[x]+=size[y];
if (size[y]>size[heavy[x]]) heavy[x]=y;
}
}
}

void dfs2(int x){
vis[x]=1;
id[x]=++tot;
num[tot]=x;
if (!head[x]) head[x]=x;
if (heavy[x]) head[heavy[x]]=head[x],dfs2(heavy[x]);
for (int i=son[x];i;i=next[i]){
int y=ed[i];
if (!vis[y]) dfs2(y);
}
}

void up(int k){
tree1[k]=max(tree1[k*2],tree1[k*2+1]);
tree2[k]=tree2[k*2]+tree2[k*2+1];
}

void build(int k,int lc,int rc){
if (lc==rc){
tree1[k]=tree2[k]=w[num[lc]];
return;
}
int mid=(lc+rc)/2;
build(k*2,lc,mid);
build(k*2+1,mid+1,rc);
up(k);
}

void change(int k,int lc,int rc,int x,int y){
if (lc==rc){
tree1[k]=tree2[k]=y;
return;
}
int mid=(lc+rc)/2;
if (x<=mid) change(k*2,lc,mid,x,y);
else change(k*2+1,mid+1,rc,x,y);
up(k);
}

int query1(int k,int lc,int rc,int l,int r){
if (l==lc && r==rc) return tree1[k];
int mid=(lc+rc)/2;
if (r<=mid) return query1(k*2,lc,mid,l,r);
if (l>mid) return query1(k*2+1,mid+1,rc,l,r);
return max(query1(k*2,lc,mid,l,mid),query1(k*2+1,mid+1,rc,mid+1,r));
}

int query2(int k,int lc,int rc,int l,int r){
if (l==lc && r==rc) return tree2[k];
int mid=(lc+rc)/2;
if (r<=mid) return query2(k*2,lc,mid,l,r);
if (l>mid) return query2(k*2+1,mid+1,rc,l,r);
return query2(k*2,lc,mid,l,mid)+query2(k*2+1,mid+1,rc,mid+1,r);
}

int qmax(int x,int y){
int ans=-oo;
while (head[x]!=head[y]){
if (deep[head[x]]<deep[head[y]]) swap(x,y);
ans=max(ans,query1(1,1,tot,id[head[x]],id[x]));
x=fa[head[x]];
}
if (deep[x]>deep[y]) swap(x,y);
ans=max(ans,query1(1,1,tot,id[x],id[y]));
return ans;
}

int qsum(int x,int y){
int ans=0;
while (head[x]!=head[y]){
if (deep[head[x]]<deep[head[y]]) swap(x,y);
ans+=query2(1,1,tot,id[head[x]],id[x]);
x=fa[head[x]];
}
if (deep[x]>deep[y]) swap(x,y);
ans+=query2(1,1,tot,id[x],id[y]);
return ans;
}

int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
for (int i=1;i<=n;++i) scanf("%d",&w[i]);
dfs1(1);
for (int i=1;i<=n;++i) vis[i]=0;
dfs2(1);
build(1,1,tot);
scanf("%d",&q);
for (int i=1;i<=q;++i){
scanf("%s%d%d",s,&x,&y);
if (s[0]=='C') change(1,1,tot,id[x],y);
else if (s[0]=='Q' && s[1]=='M') printf("%d\n",qmax(x,y));
else printf("%d\n",qsum(x,y));
}
return 0;
}

By Charlie Pan
Mar 12,2014



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  BZOJ ZJOI 树链剖分