BZOJ1036:[ZJOI2008]树的统计Count 树链剖分 / LCT

树链剖分网上的资料比较详细了。


其实我一直很怕dfs爆栈啊。。

上代码:

#include <cstdio>
#include <algorithm>
#define rep(i,l,r) for (int i=l;i<=r;++i)
#define per(i,r,l) for (int i=r;i>=l;--i)
#define feh(k,v) for (int k=first[v];k;k=next[k])
#define gt getchar()
int getx(){
	char c;int x;bool pd=false;
	for (c=gt;c!='-'&&(c<'0'||c>'9');c=gt);
	if (c=='-') c=getchar(),pd=true;
	for (x=0;c>='0'&&c<='9';c=gt)
		x=(x<<3)+(x<<1)+c-'0';
	return pd?-x:x;
}
int Max(const int &a,const int &b){return a<b?b:a;}
int upmax(int &a,const int &b){return a<b?a=b,1:0;}
const int MAX_N=30050,INF=~0U>>2;
int first[MAX_N],next[MAX_N*2],to[MAX_N*2],tal=0;
void tjb(int x,int y){
	next[++tal]=first[x];
	first[x]=tal,to[tal]=y;
	next[++tal]=first[y];
	first[y]=tal,to[tal]=x;
}
struct SegmentTree{
	int max[MAX_N<<2],sum[MAX_N<<2];
	#define lcv v<<1
	#define rcv v<<1|1
	#define lc v<<1,l,mid
	#define rc v<<1|1,mid+1,r
	inline void up(int v){
		max[v]=Max(max[lcv],max[rcv]);
		sum[v]=sum[lcv]+sum[rcv];
		}
	void modify(int v,int l,int r,int p,int x){
		if (l==r){max[v]=sum[v]=x;return;}
		int mid=l+r>>1;
		if (p<=mid) modify(lc,p,x);
			else	modify(rc,p,x);
		up(v);
		}
	int qmax(int v,int l,int r,int s,int t){
		if (s<=l&&r<=t) return max[v];
		int mid=l+r>>1,res=-INF;
		if (s<=mid) res=qmax(lc,s,t);
		if (t> mid) upmax(res,qmax(rc,s,t));
		return res;
		}
	int qsum(int v,int l,int r,int s,int t){
		if (s<=l&&r<=t) return sum[v];
		int mid=l+r>>1,res=0;
		if (s<=mid) res+=qsum(lc,s,t);
		if (t> mid) res+=qsum(rc,s,t);
		return res;
		}
}T;
int n,q;
int w[MAX_N];
int fa[MAX_N],deep[MAX_N],size[MAX_N];
int hson[MAX_N];
int dfs1(int v,int faa,int dep){
	deep[v]=dep,fa[v]=faa,size[v]=1;
	int &son=hson[v]=0;
	feh(k,v) if (to[k]!=faa){
		int tp=dfs1(to[k],v,dep+1);
		if (tp>size[son]) son=to[k];
		size[v]+=tp;
		}
	return size[v];
}
int pos[MAX_N],top[MAX_N];
int Time=0;
void dfs2(int v,bool heavy){
	pos[v]=++Time;
	T.modify(1,1,n,pos[v],w[v]);
	top[v]=heavy?top[fa[v]]:v;
	if (hson[v]) dfs2(hson[v],true);
	feh(k,v) if (to[k]!=hson[v]&&to[k]!=fa[v])
		dfs2(to[k],false);
}
void Change(int v,int x){
	T.modify(1,1,n,pos[v],x);
}
void Qmax(int x,int y){
	int res=-INF;
	for (;top[x]!=top[y];x=fa[top[x]]){
		if (deep[top[x]]<deep[top[y]]) x^=y^=x^=y;
		upmax(res,T.qmax(1,1,n,pos[top[x]],pos[x]));
		}
	if (pos[x]>pos[y]) x^=y^=x^=y;
	upmax(res,T.qmax(1,1,n,pos[x],pos[y]));
	printf("%d\n",res);
}
void Qsum(int x,int y){
	int res=0;
	for (;top[x]!=top[y];x=fa[top[x]]){
		if (deep[top[x]]<deep[top[y]]) x^=y^=x^=y;
		res+=T.qsum(1,1,n,pos[top[x]],pos[x]);
		}
	if (pos[x]>pos[y]) x^=y^=x^=y;
	res+=T.qsum(1,1,n,pos[x],pos[y]);
	printf("%d\n",res);
}
char opt;
int main(){
	freopen("ct.in","r",stdin);
	freopen("ct.out","w",stdout);
	n=getx();
	rep(i,2,n) tjb(getx(),getx());
	rep(i,1,n) w[i]=getx();
	dfs1(1,0,0);dfs2(1,0);
	q=getx();
	rep(i,1,q){
		for (opt=gt;opt!='H'&&opt!='M'&&opt!='S';opt=gt);
		int x=getx(),y=getx();
		if (opt=='H') Change(x,y);
		if (opt=='M') Qmax(x,y);
		if (opt=='S') Qsum(x,y);
		}
}



树链剖分能做的LCT大概都能做吧。。

LCT常数不小就是了。但没爆栈风险。。囧

LCT还没写这题。囧

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值