稍微码一下蒟蒻的链剖序+线段树 大概是模板吧……

80 篇文章 0 订阅
14 篇文章 0 订阅

二话不说上代码

这道题哒↓

CodeVS 2460 树的统计

BZOJ 1036: [ZJOI2008]树的统计Count

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;	int n,m;
const int INF=0x3f3f3f3f;

struct t1{
	int to,nxt;
}edge[60057];	int cnt_edge=0;
int fst[30057];

void addedge(int x,int y){
	edge[++cnt_edge].to=y;
	edge[cnt_edge].nxt=fst[x];
	fst[x]=cnt_edge;
}

int root;
int siz[30057],son[30057],top[30057],fth[30057];
int dpt[30057];
void dfs1(int x){
	siz[x]=1;
	son[x]=0;
	for(int tmp=fst[x];tmp;tmp=edge[tmp].nxt){
		if(edge[tmp].to==fth[x])	continue;
		fth[edge[tmp].to]=x;
		dpt[edge[tmp].to]=dpt[x]+1;
		dfs1(edge[tmp].to);
		siz[x]+=siz[edge[tmp].to];
		son[x]=siz[edge[tmp].to]>siz[son[x]]?edge[tmp].to:son[x];
	}
}

int dfn[30057],cnt_dfs=0;
void dfs2(int x,int tp){
	top[x]=tp;
	dfn[x]=++cnt_dfs;
	if(son[x])	dfs2(son[x],tp);
	for(int tmp=fst[x];tmp;tmp=edge[tmp].nxt){
		if(edge[tmp].to==fth[x]||edge[tmp].to==son[x])	continue;
		dfs2(edge[tmp].to,edge[tmp].to);
	}
}

int k[30057];
struct t2{
	int sum,mx;
}node[130057];

void updata(int now){
	node[now].sum=node[now<<1].sum+node[now<<1|1].sum;
	node[now].mx=max(node[now<<1].mx,node[now<<1|1].mx);
}
void build(int now,int l,int r){
	if(l==r){
		node[now].sum=node[now].mx=k[l];
//	printf("%d %d:   sum: %d   max: %d\n",l,r,node[now].sum,node[now].mx);
		return ;
	}
	int mid=(l+r)>>1;
	build(now<<1,l,mid);
	build(now<<1|1,mid+1,r);
	updata(now);
	
//	printf("%d %d:   sum: %d   max: %d\n",l,r,node[now].sum,node[now].mx);
}
void modify(int now,int l,int r,int loc,int q){
	if(l==loc&&r==loc){
		node[now].sum=node[now].mx=q;
		return ;
	}
	int mid=(l+r)>>1;
	if(loc<=mid)	modify(now<<1,l,mid,loc,q);
	else modify(now<<1|1,mid+1,r,loc,q);
	updata(now);
}
int q1(int now,int l,int r,int L,int R){
	if(L<=l&&r<=R)
		return node[now].mx;
	int mid=(l+r)>>1;
	int tp=-INF;
	if(L<=mid)	tp=max(tp,q1(now<<1,l,mid,L,R));
	if(mid<R)	tp=max(tp,q1(now<<1|1,mid+1,r,L,R));
	return tp;
}
int q2(int now,int l,int r,int L,int R){
	if(L<=l&&r<=R)
		return node[now].sum;
	int mid=(l+r)>>1;
	int tp=0;
	if(L<=mid)	tp=q2(now<<1,l,mid,L,R);
	if(mid<R)	tp+=q2(now<<1|1,mid+1,r,L,R);
	return tp;
}

int main(){
	memset(fst,0,sizeof(fst));
	memset(siz,0,sizeof(siz));
	memset(son,0,sizeof(son));
	memset(dpt,0,sizeof(dpt));
	
	freopen("1.in","r",stdin);
	
	scanf("%d",&n);
	for(int i=1;i<n;++i){
		int a,b;
		scanf("%d%d",&a,&b);
		addedge(a,b);
		addedge(b,a);
	}
	root=(n>>2)+1;
	top[root]=root;
	fth[root]=0;
	dpt[0]=-1;
	
	dfs1(root);
	dfs2(root,root);
	for(int i=1;i<=n;++i)	scanf("%d",&k[dfn[i]]);
	
	build(1,1,n);
	
	scanf("%d",&m);
	char tmp[10];
	while(m--){
		scanf("%s",tmp);
		if(tmp[0]=='C'){
			int a,b;
			scanf("%d%d",&a,&b);
			modify(1,1,n,dfn[a],b);
		}
		else{
			int low,high;
			scanf("%d%d",&low,&high);
			if(dpt[top[high]]>dpt[top[low]])	swap(low,high);
			
			if(tmp[1]=='S'){
				int ans=0;
				while(top[low]!=top[high]){
					ans+=q2(1,1,n,dfn[top[low]],dfn[low]);
					low=fth[top[low]];
					if(!low)	break;
					if(dpt[top[low]]<dpt[top[high]])	swap(low,high);
				}
				if(low)	ans+=q2(1,1,n,min(dfn[high],dfn[low]),max(dfn[high],dfn[low]));
				printf("%d\n",ans);
			}
			if(tmp[1]=='M'){
				int ans=-INF;
				while(top[low]!=top[high]){
					ans=max(ans,q1(1,1,n,dfn[top[low]],dfn[low]));
					low=fth[top[low]];
					if(!low)	break;
					if(dpt[top[low]]<dpt[top[high]])	swap(low,high);
				}
				if(low)	ans=max(ans,q1(1,1,n,min(dfn[high],dfn[low]),max(dfn[high],dfn[low])));
				printf("%d\n",ans);
			}
		}
	}
	
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值