您的位置:首页 > 其它

BZOJ 1036 [ZJOI2008]树的统计Count

2016-10-13 22:41 267 查看
Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

  

【题目分析】

树链剖分+线段树。

【代码】

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n,root=1,node,q,x,y;
int h[30001],ne[60001],to[60001],en=0;
int fa[30001],dep[30001],son[30001],siz[30001],top[30001],pos[30001],w[30001];
int v[30001]; char opt[11];
struct node{
int l,r,max,sum;
}t[30001*8];
int read()
{
int ret=0,f=1;
char ch=getchar();
while (ch>'9'||ch<'0')
{
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9')
{
ret*=10;
ret+=ch-'0';
ch=getchar();
}
return ret*f;
}
void add(int a,int b)
{ne[en]=h[a];to[en]=b;h[a]=en++;}
void dfs1(int k)
{
siz[k]=1;
for (int i=h[k];i>=0;i=ne[i])
{
if (to[i]!=fa[k])
{
fa[to[i]]=k;
dep[to[i]]=dep[k]+1;
dfs1(to[i]);
siz[k]+=siz[to[i]];
if (siz[to[i]]>siz[son[k]]) son[k]=to[i];
}
}
}
void dfs2(int k,int tp)
{
top[k]=tp;
pos[k]=++node;
v[pos[k]]=w[k];
if (son[k]==0) return ;
dfs2(son[k],tp);
for (int i=h[k];i>=0;i=ne[i])
if (to[i]!=son[k]&&to[i]!=fa[k])
dfs2(to[i],to[i]);
}
void update(int k,int x,int y)
{
if (t[k].l==t[k].r)
{
t[k].sum=t[k].max=v[t[k].l];
return ;
}
if (x<=(t[k].l+t[k].r)/2) update(k*2,x,y);
else update(k*2+1,x,y);
t[k].sum=t[k*2].sum+t[k*2+1].sum;
t[k].max=max(t[k*2].max,t[k*2+1].max);
}
int qmax(int k,int L,int R)
{
if (t[k].r<L||t[k].l>R) return -0x3f3f3f3f;
if (t[k].l>=L&&t[k].r<=R) return t[k].max;
return max(qmax(k*2,L,R),qmax(k*2+1,L,R));
}
int qsum(int k,int L,int R)
{
if (t[k].r<L||t[k].l>R) return 0;
if (t[k].l>=L&&t[k].r<=R) return t[k].sum;
return qsum(k*2,L,R)+qsum(k*2+1,L,R);
}
void build(int k,int L,int R)
{
t[k].l=L;t[k].r=R;
if (L==R)
{
t[k].sum=t[k].max=v[L];
return;
}
build(k*2,L,(L+R)/2);
build(k*2+1,(L+R)/2+1,R);
t[k].sum=t[k*2].sum+t[k*2+1].sum;
t[k].max=max(t[k*2].max,t[k*2+1].max);
}
int main()
{
memset(h,-1,sizeof h);
n=read();
for (int i=1;i<n;++i)
{
int a,b;
a=read();b=read();
add(a,b);
add(b,a);
}
for (int i=1;i<=n;++i) w[i]=read();
dfs1(root);
dfs2(root,root);
build(1,1,n);
q=read();
while (q--)
{
scanf("%s",opt);
if (opt[0]=='C')
{
x=read();y=read();
w[x]=y;
v[pos[x]]=y;
update(1,pos[x],y);
}
else if (opt[1]=='M')
{
int ans=-0x3f3f3f3f;
x=read();y=read();
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,qmax(1,pos[top[x]],pos[x]));
x=fa[top[x]];
}
if (dep[x]<dep[y]) swap(x,y);
ans=max(ans,qmax(1,pos[y],pos[x]));
printf("%d\n",ans);
}
else
{
int ans=0;
x=read();y=read();
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
ans+=qsum(1,pos[top[x]],pos[x]);
x=fa[top[x]];
}
if (dep[x]<dep[y]) swap(x,y);
ans+=qsum(1,pos[y],pos[x]);
printf("%d\n",ans);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: