【BZOJ1017】魔兽地图
【BZOJ2002】弹飞绵羊

【BZOJ1036】树的统计

Zarxdy34 posted @ 2015年11月21日 14:36 in BZOJ with tags 树链剖分 , 332 阅读

    裸的树链剖分。

 

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=30010,inf=~0U>>1;

struct Segment_Tree
{
	#define ls (o<<1)
	#define rs ((o<<1)|1)
	#define mid ((l+r)>>1)
	int sum[maxn<<2],maxv[maxn<<2];
	int tag[maxn<<2],tagv[maxn<<2];
	int n;
	int a,b,v;

	void Update(int o)
	{
		sum[o]=sum[ls]+sum[rs];
		maxv[o]=max(maxv[ls],maxv[rs]);
	}

	void Mark(int o,int l,int r,int markv)
	{
		sum[o]=markv*(r-l+1);
		maxv[o]=markv;
	}

	void Push_Down(int o,int l,int r)
	{
		if (l==r || !tag[o]) return;
		Mark(ls,l,mid,tagv[o]);
		Mark(rs,mid+1,r,tagv[o]);
		tag[ls]=tag[r]=1;
		tagv[ls]=tagv[rs]=tagv[o];
		tagv[o]=tag[o]=0;
	}

	void Build(int o,int l,int r,int *a)
	{
		if (l==r) {sum[o]=maxv[o]=a[l];return;}
		Build(ls,l,mid,a);
		Build(rs,mid+1,r,a);
		Update(o);
	}

	void Change(int o,int l,int r)
	{
		if (l>=a && r<=b) {Mark(o,l,r,v);tag[o]=1;tagv[o]=v;return;}
		Push_Down(o,l,r);
		if (a<=mid) Change(ls,l,mid);
		if (b>mid)  Change(rs,mid+1,r);
		Update(o);
	}

	int Query_Max(int o,int l,int r)
	{
		if (l>=a && r<=b) return maxv[o];
		Push_Down(o,l,r);
		int res=-inf;
		if (a<=mid) res=max(res,Query_Max(ls,l,mid));
		if (b>mid)  res=max(res,Query_Max(rs,mid+1,r));
		Update(o);
		return res;
	}

	int Query_Sum(int o,int l,int r)
	{
		if (l>=a && r<=b) return sum[o];
		Push_Down(o,l,r);
		int res=0;
		if (a<=mid) res+=Query_Sum(ls,l,mid);
		if (b>mid)  res+=Query_Sum(rs,mid+1,r);
		Update(o);
		return res;
	}
	
	void Change(int x,int _v) {a=b=x;v=_v;Change(1,1,n);}
	int Query_Max(int _a,int _b) {a=_a;b=_b;return Query_Max(1,1,n);}
	int Query_Sum(int _a,int _b) {a=_a;b=_b;return Query_Sum(1,1,n);}
	#undef ls
	#undef rs
	#undef mid
}ST;

struct Tree
{
	int head[maxn],next[maxn<<1],E[maxn<<1],Ecnt;
	int top[maxn],fa[maxn],dep[maxn];
	int wson[maxn],id[maxn],ids;
	int temp[maxn];

	void Add_Edge(int x,int y) {next[++Ecnt]=head[x];head[x]=Ecnt;E[Ecnt]=y;next[++Ecnt]=head[y];head[y]=Ecnt;E[Ecnt]=x;}

	int DFS1(int x,int father,int depth)
	{
		int sons=0,maxsons=0;
		fa[x]=father;dep[x]=depth;
		for (int i=head[x];i;i=next[i]) if (E[i]!=father)
		{
			int tsons=DFS1(E[i],x,depth+1);
			sons+=tsons;
			if (tsons>maxsons) maxsons=tsons,wson[x]=E[i];
		}
		return sons+1;
	}

	void DFS2(int x,int is_wson)
	{
		id[x]=++ids;
		if (is_wson==1) top[x]=top[fa[x]];else top[x]=x;
		if (wson[x]) DFS2(wson[x],1);
		for (int i=head[x];i;i=next[i]) if (E[i]!=fa[x] && E[i]!=wson[x]) DFS2(E[i],0);
	}

	void Build(int *a,int n)
	{
		(void)DFS1(1,0,1);
		DFS2(1,0);
		for (int i=1;i<=n;i++) temp[id[i]]=a[i];
		ST.n=n;
		ST.Build(1,1,n,temp);
	}

	void Change(int x,int y) {ST.Change(id[x],y);}
	
	int Query_Max(int x,int y)
	{
		int res=-inf;
		while (top[x]!=top[y])
		{
			int fx=top[x],fy=top[y];
			if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
			if (top[x]==x) res=max(res,ST.Query_Max(id[x],id[x])),x=fa[x];
			else res=max(res,ST.Query_Max(id[top[x]],id[x])),x=top[x];
		}
		if (dep[x]>dep[y]) swap(x,y);
		res=max(res,ST.Query_Max(id[x],id[y]));
		return res;
	}

	int Query_Sum(int x,int y)
	{
		int res=0,cx=0,cy=0;
		while (top[x]!=top[y])
		{
			int fx=top[x],fy=top[y];
			if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy),swap(cx,cy);
			if (top[x]==x)
			{
				if (!cx) res+=ST.Query_Sum(id[x],id[x]);
				cx=0;
				x=fa[x];
			}
			else
			{
				res+=ST.Query_Sum(id[top[x]],(cx?id[fa[x]]:id[x]));
				cx=1;
				x=top[x];
			}
		}
		if (dep[x]>dep[y]) swap(x,y),swap(cx,cy);
		res+=ST.Query_Sum(id[x],id[y]);
		if (cx) res-=ST.Query_Sum(id[x],id[x]);
		if (cy) res-=ST.Query_Sum(id[y],id[y]);
		return res;
	}
}T;

void read(int &x) {char ch=' ';int f=1;while (((ch=getchar())<'0' || ch>'9') && ch!='-');if (ch=='-') f=-1,x=0;else x=ch-'0';while ((ch=getchar())<='9' && ch>='0') x=x*10+ch-'0';x*=f;}

int a[maxn];
int n,q;

int main()
{
	read(n);
	for (int i=1,x,y;i<n;i++) read(x),read(y),T.Add_Edge(x,y);
	for (int i=1;i<=n;i++) read(a[i]);
	T.Build(a,n);
	read(q);
	while (q--)
	{
		static char cor[10];
		static int x,y;
		scanf("%s",cor);
		read(x),read(y);
		if (cor[0]=='C') T.Change(x,y);
		else if (cor[1]=='M') printf("%d\n",T.Query_Max(x,y));
		else printf("%d\n",T.Query_Sum(x,y));
	}
	return 0;
}

登录 *


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