BZOJ 1036: [ZJOI2008]树的统计Count

Fancy posted @ 2015年7月08日 22:07 in BZOJ , 359 阅读

题目大意:一棵树上有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本身

 

树链剖分,维护点权

裸题但才开始一直WA,没看见还有负数。。。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
const int N=30005;
struct abcd  { int a,b,c; } v[N*2];
struct TREE  { int lc,rc,l,r,sum,max; } tree[N*4];
vector<int> to[N];
char s[7];
int n,totw,tot=1,t,x,y;
int vis[N],dep[N],fa[N],son[N],siz[N],top[N],w[N],val[N],c[N];
void DFS(int x)
{
	int t=0;
	vis[x]=1;dep[x]=dep[fa[x]]+1;
	for(int i=0;i<to[x].size();i++)
	{
		int y=to[x][i];
		if(!vis[y])
		{
			t=1;
			fa[y]=x;DFS(y);siz[x]+=siz[y];
			if(siz[y]>siz[son[x]]) son[x]=y;
		}
	}
}
void DFS2(int x)
{
	if(son[x])
	{
		top[son[x]]=top[x];
	    w[son[x]]=++totw;
	    DFS2(son[x]);
	}
	for(int i=0;i<to[x].size();i++)
	{
		int y=to[x][i];
		if(y!=fa[x]&&y!=son[x])
		{
			top[y]=y;
			w[y]=++totw;
			DFS2(y);
		}
	}
}
void build(int x,int l,int r)
{
	tree[x].l=l;tree[x].r=r;
	if(r==l)
	{
		tree[x].sum=val[l];
		tree[x].max=val[l];
		return;
	}
	int mid=(l+r)/2;
	tree[x].lc=++tot; build(tree[x].lc,l,mid);
	tree[x].rc=++tot; build(tree[x].rc,mid+1,r);
	tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum;
	tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max);
}
void change(int x,int v,int d)
{
	if(tree[x].l==tree[x].r)
	{
		tree[x].sum=d;tree[x].max=d;return;
	}
	int mid=(tree[x].l+tree[x].r)/2;
	if(v<=mid) change(tree[x].lc,v,d);
	else change(tree[x].rc,v,d);
	tree[x].sum=tree[tree[x].lc].sum+tree[tree[x].rc].sum;
	tree[x].max=max(tree[tree[x].lc].max,tree[tree[x].rc].max);
}
int querysum(int x,int l,int r)
{
	if(l>r) swap(l,r);
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].sum;
	int mid=(tree[x].l+tree[x].r)/2;
	int ans=0;
	if(l<=mid) ans+=querysum(tree[x].lc,l,r);
	if(mid<r)  ans+=querysum(tree[x].rc,l,r);
	return ans;
}
int querymax(int x,int l,int r)
{
	if(l>r) swap(l,r);
	if(l<=tree[x].l&&tree[x].r<=r) return tree[x].max;
	int mid=(tree[x].l+tree[x].r)/2;
	int ans=-30000;
	if(l<=mid) ans=max(ans,querymax(tree[x].lc,l,r));
	if(mid<r)  ans=max(ans,querymax(tree[x].rc,l,r));
	return ans;
}
int Sum(int x,int y)
{
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) swap(x,y),swap(f1,f2);
		return querysum(1,w[f1],w[x])+Sum(fa[f1],y);
	}
	else return querysum(1,w[x],w[y]);
}
int Max(int x,int y)
{
	int f1=top[x],f2=top[y];
	if(f1!=f2)
	{
		if(dep[f1]<dep[f2]) {swap(x,y);swap(f1,f2);}
		return max(querymax(1,w[f1],w[x]),Max(fa[f1],y));
	}
	else return querymax(1,w[x],w[y]);
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&v[i].a,&v[i].b);
		to[v[i].a].push_back(v[i].b);
		to[v[i].b].push_back(v[i].a);
	}
	for(int i=1;i<=n;i++) scanf("%d",&c[i]);
	for(int i=1;i<=n;i++) siz[i]=1;
	DFS(1);
	top[1]=1;w[1]=++totw;DFS2(1);
	for(int i=1;i<=n;i++) val[w[i]]=c[i];
	build(1,1,totw);
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		scanf("%s%d%d",&s,&x,&y);
		if(s[0]=='C') change(1,w[x],y);
		else if(s[1]=='M') printf("%d\n",Max(x,y));
		else printf("%d\n",Sum(x,y));
	}
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter