树链剖分

P1505 [国家集训队] 旅游

  • 思路:
    边权转点权,由于父亲可能有许多儿子,所以一条边的权值需要付给儿子
点击查看代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2e6;
inline int read(){
	ll x=0,f=1;
	char c=getchar();
	while(c<'0'||c>'9') {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		x=x*10+c-'0';
		c=getchar();
	}
	return x*f;
}
struct edge{
	int to,nxt,w;
}z[2*N];
struct Tree{
	int l,r;
	ll sum,minn,maxx,lazy;
}t[4*N];
struct lian{
	int maxxson,top,fa,dep;
	ll son;
}l[N];
int id[N]; 
int n,cnt,m,num=-1;
int ww[N];
int val[N]; //边权->点权 
int h[N];
void add(int u,int v,int w){
	z[++cnt].to=v;
	z[cnt].nxt=h[u];
	z[cnt].w=w;
	h[u]=cnt;
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			ww[y]=z[i].w;
			//cout<<"y: "<<y<<" "<<ww[y]<<"\n";
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			}
		}
	}
}
void DFS(int x,int top){
	l[x].top=top;
	id[x]=++num;
	val[num]=ww[x];
	if(!l[x].maxxson ) return ;
	else{
		DFS(l[x].maxxson,top);
		for(int i=h[x];i;i=z[i].nxt){
			int y=z[i].to;
			if(y==l[x].fa||y==l[x].maxxson ) continue;
			else DFS(y,y); 
		}
	} 
}
void pushup(int x){
	t[x].sum=t[x*2].sum+t[x*2+1].sum;
	t[x].minn=min(t[x*2].minn,t[x*2+1].minn);
	t[x].maxx=max(t[x*2].maxx,t[x*2+1].maxx);
}
void lazzy(int x){
	if(t[x].lazy){
		t[x*2].lazy^=t[x].lazy;
		t[x*2+1].lazy^=t[x].lazy;
		//if(t[x*2].lazy!=0){
			t[x*2].sum=-t[x*2].sum;
			int MAX=t[x*2].maxx,MIN=t[x*2].minn;
			t[x*2].minn=-MAX;
			t[x*2].maxx=-MIN;	
		//}
		//if(t[x*2+1].lazy!=0){
			t[x*2+1].sum=-t[x*2+1].sum;
			MAX=t[x*2+1].maxx,MIN=t[x*2+1].minn;
			t[x*2+1].minn=-MAX;
			t[x*2+1].maxx=-MIN;		
		//}
		t[x].lazy^=1; 
	}
		
}
void build(int l,int r,int x){
	t[x].l=l;
	t[x].r=r;
	t[x].lazy=0;
	if(l==r){
		
		t[x].sum=val[l];
		t[x].minn=val[l];
		t[x].maxx=val[l];
		//cout<<l<<" "<<val[l]<<" "<<x<<" "<<t[x].sum<<endl;
		return ;
	} 
	int mid=l+r>>1;
	build(l,mid,x*2);
	build(mid+1,r,x*2+1);
	pushup(x);
} 
void one_chan(int y,int k,int x){
	if(t[x].l==t[x].r){
		t[x].sum=k;
		t[x].minn=k;
		t[x].maxx=k;
		return ;
	}
	lazzy(x);
	int mid=t[x].l+t[x].r>>1;
	if(y<=mid){
		one_chan(y,k,x*2);
	}
	else{
		one_chan(y,k,x*2+1);
	}
	pushup(x);
}
void chan(int l,int r,int x){
	if(t[x].l>=l&&t[x].r<=r){
		t[x].lazy^=1;
		//if(t[x].lazy!=0){
			t[x].sum=-t[x].sum;
			int MAX=t[x].maxx,MIN=t[x].minn;
			t[x].minn=-MAX;
			t[x].maxx=-MIN;	
		//}
		return;
	}
	lazzy(x);
	int mid=t[x].l+t[x].r>>1;
	if(l<=mid){
		chan(l,r,x*2);
	}
	if(r>mid){
		chan(l,r,x*2+1);
	}
	pushup(x);
}
void first_chan(int a,int b){
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		chan(id[l[a].top],id[a],1);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	chan(id[a]+1,id[b],1);
}
ll query_sum(int l,int r,int x){
	//cout<<"l r"<<l<<" "<<r<<endl;
	if(t[x].l>=l&&t[x].r<=r){
		return t[x].sum;
	}
	lazzy(x);
	ll sum=0;
	int mid=t[x].l+t[x].r>>1;
	if(l<=mid){
		sum+=query_sum(l,r,x*2);
	}
	if(r>mid){
		sum+=query_sum(l,r,x*2+1);
	}
	pushup(x);
	return sum;
}
ll Ask_sum(int a,int b){
	ll sum=0;
	int A=a;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		sum+=query_sum(id[l[a].top],id[a],1);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	sum+=query_sum(id[a]+1,id[b],1);
	return sum;
}
ll query_max(int l,int r,int x){
	if(t[x].l>=l&&t[x].r<=r){
		return t[x].maxx;
	}
	lazzy(x);
	int mid=t[x].l+t[x].r>>1;
	ll maxx=-1e9;
	if(l<=mid){
		maxx=max(maxx,query_max(l,r,x*2));
	}
	if(r>mid){
		maxx=max(maxx,query_max(l,r,x*2+1)); 
	}
	pushup(x);
	return maxx; 
}
ll Ask_max(int a,int b){
	ll maxx=-1e9;
	int A=a;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		maxx=max(maxx,query_max(id[l[a].top],id[a],1));
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	maxx=max(maxx,query_max(id[a]+1,id[b],1));
	return maxx;
}
ll query_min(int l,int r,int x){
	if(t[x].l>=l&&t[x].r<=r){
		return t[x].minn;
	}
	lazzy(x);
	int mid=t[x].l+t[x].r>>1;
	ll minn=1e9;
	if(l<=mid){
		minn=min(minn,query_min(l,r,x*2));
	} 
	if(r>mid){
		minn=min(minn,query_min(l,r,x*2+1));
	}
	pushup(x);
	return minn;
}
ll Ask_min(int a,int b){
	ll minn=1e9;
	int A=a;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		minn=min(minn,query_min(id[l[a].top],id[a],1));
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	minn=min(minn,query_min(id[a]+1,id[b],1));
	return minn;
}
int vis_a[N],vis_b[N];
int main(){
//	freopen("P1505_1.in","r",stdin);
	n=read();
	for(int i=1;i<n;i++){
		int u,v,w;
		u=read(),v=read(),w=read();
		vis_a[i]=u;
		vis_b[i]=v;
		add(u,v,w);
		add(v,u,w); 
	}
	dfs(0,-1);
	DFS(0,0);
	build(0,n-1,1);
	m=read();
	while(m--){
		string opt;
		cin>>opt;
		if(opt=="C"){
			int x,w;
			x=read(),w=read();
			if(l[vis_a[x]].dep>l[vis_b[x]].dep) one_chan(id[vis_a[x]],w,1);
			else one_chan(id[vis_b[x]],w,1);
		}
		if(opt=="N"){
			int u,v;
			u=read(),v=read();
			first_chan(u,v);
		}
		if(opt=="SUM"){
			int u,v;
			u=read(),v=read();
			cout<<Ask_sum(u,v)<<"\n";
		}
		if(opt=="MAX"){
			int u,v;
			u=read(),v=read();
			cout<<Ask_max(u,v)<<"\n";
		}
		if(opt=="MIN"){
			int u,v;
			u=read(),v=read();
			cout<<Ask_min(u,v)<<"\n";
		}
	}	
}

P2590 [ZJOI2008] 树的统计

跟板子没什么两样

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1000003;
struct node{
	int fa,maxxson,son,dep,top,num;
}l[N];
struct Node{
	int to,nxt;
}z[N];
struct mode{
	int l,r,siz,lazy,sum,maxx;
}t[4*N];
int a[N];
int h[N];
int w[N];
int Num;
int root;
void dfs(int x,int fa){
	l[x].son=1;
	l[x].dep=l[fa].dep+1;
	l[x].fa=fa;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			}
		}
	}
}
void dfs1(int x,int fa,int Top){
	Num++;
	l[x].num=Num;
	l[x].top=Top;
	w[Num]=a[x];
	if(!l[x].maxxson) return ;
	else{
		dfs1(l[x].maxxson,x,Top);
	}
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa||y==l[x].maxxson) continue;
		else{
			dfs1(y,x,y);
		}
	}
}
int n,q;
int cnt;
void add(int a,int b){
	cnt++;
	z[cnt].to=b;
	z[cnt].nxt=h[a];
	h[a]=cnt;
}
void chan(int x,int p,int k ){
	if(t[k].l==t[k].r){
		t[k].sum=p;
		t[k].maxx=p;
		return ;
	}
	int mid=t[k].l+t[k].r>>1;
	if(x<=mid){
		chan(x,p,k*2);
	}
	else{
		chan(x,p,k*2+1);
	}
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
void build(int l,int r,int k){
	t[k].l=l;
	t[k].r=r;
	if(l==r){
		t[k].sum=w[l];
		t[k].maxx=w[l];
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
}
int query_tree(int l,int r,int k){
	if(t[k].l>=l&&t[k].r<=r){
		return t[k].maxx;
	}
	int mid=t[k].l+t[k].r>>1;
	int ans=-1e9;
	if(l<=mid) ans=query_tree(l,r,k*2);
	if(r>mid) ans=max(ans,query_tree(l,r,k*2+1));
	return ans;
}
int qury(int a,int b){
	int ans=-1e9;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep){
			swap(a,b);
		}
		ans=max(ans,query_tree(l[l[a].top].num,l[a].num,1));
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	ans=max(ans,query_tree(l[a].num,l[b].num,1));
	return ans;
}
int quury_tree(int l,int r,int k){
	if(t[k].l>=l&&t[k].r<=r){
		return t[k].sum;
	}
	int mid=t[k].l+t[k].r>>1;
	int ans=0;
	if(l<=mid) ans+=quury_tree(l,r,k*2);
	if(r>mid) ans+=quury_tree(l,r,k*2+1);
	return ans;
}
int quury(int a,int b){
	int ans=0;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep){
			swap(a,b);
		}
		ans+=quury_tree(l[l[a].top].num,l[a].num,1);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	ans+=quury_tree(l[a].num,l[b].num,1);
	return ans;
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%lld%lld",&a,&b);
		add(a,b);
		add(b,a);
	}
	for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
	scanf("%lld",&q);
	l[0].dep=0;
	dfs(1,0);
	dfs1(1,0,1);
	build(1,n,1);
	for(int i=1;i<=q;i++){
		string s;
		cin>>s;
		if(s=="CHANGE"){
			int u,t;
			scanf("%lld%lld",&u,&t);
			chan(l[u].num,t,1);
		}
		if(s=="QMAX"){
			int u,v;
			scanf("%lld%lld",&u,&v);
			int ans=qury(u,v);
			printf("%lld\n",ans);
		}
		if(s=="QSUM"){
			int u,v;
			scanf("%lld%lld",&u,&v);
			int ans=quury(u,v);
			printf("%lld\n",ans);
		}
	}
}

P3038 [USACO11DEC] Grass Planting G

依旧是边权转点权

点击查看代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5;
struct node{
	int to,nxt,w;
}z[2*N];
struct tree{
	int l,r,lazy;
	ll sum,maxx,minn;
}t[4*N];
struct edge{
	int son,maxxson,top,fa,dep;
}l[N];
int id[N],val[N],ww[N],h[N];
int cnt,num,n,m;
void add(int a,int b,int c){
	z[++cnt].to=b;
	z[cnt].nxt=h[a];
	z[cnt].w=c;
	h[a]=cnt;
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[l[x].maxxson ].son=-1;
	for(int i=h[x];i;i=z[i].nxt ){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			ww[y]=z[i].w;
			dfs(y,x);
			if(l[y].son>l[l[x].maxxson ].son ){
				l[x].maxxson=y;
				l[l[x].maxxson ].son=l[y].son;
			}
		}
	}
}
void DFS(int x,int top){
	l[x].top=top;
	id[x]=++num;
	//cout<<x<<" "<<id[x]<<endl;
	val[num]=ww[x];
	if(!l[x].maxxson ) return ;
	else{
		DFS(l[x].maxxson,top);
		for(int i=h[x];i;i=z[i].nxt){
			int y=z[i].to;
			if(y==l[x].fa||y==l[x].maxxson ) continue;
			else{
				DFS(y,y);
			} 
		}
	}
}
void pushup(int x){
	t[x].sum=t[x*2].sum+t[x*2+1].sum;
}
void lazzy(int x){
	if(t[x].lazy){
		t[x*2].lazy+=t[x].lazy;
		t[x*2+1].lazy+=t[x].lazy;
		t[x*2].sum+=(t[x*2].r-t[x*2].l+1)*t[x].lazy;
		t[x*2+1].sum+=(t[x*2+1].r-t[x*2+1].l+1)*t[x].lazy;
		t[x].lazy=0;
	}
}
void build(int l,int r,int x){
	t[x].l=l;
	t[x].r=r;
	t[x].lazy=0;
	if(l==r){
		t[x].sum=val[l];
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,x*2);
	build(mid+1,r,x*2+1);
	pushup(x);
}
void Chan(int l,int r,int x){
	if(t[x].l>=l&&t[x].r<=r){
		t[x].lazy+=1;
		t[x].sum+=(t[x].r-t[x].l+1);
		return;
	}
	lazzy(x);
	int mid=t[x].l+t[x].r>>1;
	if(l<=mid){
		Chan(l,r,x*2); 
	}
	if(r>mid){
		Chan(l,r,x*2+1);
	}
	pushup(x);
}
void chan(int a,int b){
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		Chan(id[l[a].top],id[a],1);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	Chan(id[a]+1,id[b],1);
}
ll query(int l,int x){
	if(t[x].l==t[x].r){
		//cout<<t[x].l<<" "<<x<<" "<<t[x].sum<<endl;
		return t[x].sum;
	} 
	int mid=t[x].l+t[x].r>>1;
	lazzy(x);
	ll sum;
	if(l<=mid){
		sum=query(l,x*2);
	}
	else{
		sum=query(l,x*2+1);
	}
	pushup(x);
	return sum;
}
void init(){
	cin>>n>>m;
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		add(u,v,0);
		add(v,u,0);
	}
	dfs(1,0);
	DFS(1,1); 
	build(1,n,1);
	while(m--){
		char op;
		int u,v;
		cin>>op>>u>>v;
		if(op=='P'){                                
			chan(u,v);
		}
		if(op=='Q'){
			if(l[u].dep>l[v].dep) cout<<query(id[u],1)<<"\n";
			else cout<<query(id[v],1)<<"\n";
		}
	}
}
int main(){
	init();
}

P3128 [USACO15DEC] Max Flow P

  • 思路:
    这道题好像有两种做法,对于加边权,我们既可以用线段树来做,也可以用树上差分来做。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,k; 
struct node{
	int to,nxt;
}z[1000003];
struct no{
	int dep,fa,id,top,maxxson,son;
}l[1000004];
int num;
int h[1000003];
int d[1000040];
inline void dfs(int x,int fa){
	l[x].dep=l[fa].dep+1;
	l[x].fa=fa;
	l[x].son=1;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			}
		}
	}
}
inline void dfss(int x,int fa,int top){
	l[x].id=++num;
	l[x].top=top;
	if(!l[x].maxxson) return ;
	else{
		dfss(l[x].maxxson,x,top);
		for(int i=h[x];i;i=z[i].nxt){
			int y=z[i].to;
			if(fa==y||y==l[x].maxxson) continue;
			else{
				dfss(y,x,y);
			}
		}
	}
}
int cnt;
inline void add(int x,int y){
	cnt++;
	z[cnt].to=y;
	z[cnt].nxt=h[x];
	h[x]=cnt;
}
inline int lca(int a,int b){
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	return a;
}
int ans=0;
void __(int x,int fa){
	for(int i=h[x];i;i=z[i].nxt){
		int to=z[i].to;
		if(to==fa) continue;
		else{
			__(to,x);
			d[x]=d[x]+d[to];
		}
	}
	ans=max(ans,d[x]);
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	l[0].dep=0;
	dfs(1,0);
	dfss(1,0,1);
	for(int i=1;i<=k;i++){
		int s,t;
		scanf("%d%d",&s,&t);
		int LCA=lca(s,t);
	//	cout<<lca(s,t)<<endl;
		d[s]++;
		d[t]++;
		d[LCA]--;
		d[l[LCA].fa]--;
	}
	__(1,0);
	cout<<ans<<endl;
}

P3178 [HAOI2015] 树上操作

跟板子题没什么两样

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int to,nxt;
}z[1000040];
struct tree{
	int l,r,lazy,sum;
}t[1000040];
struct Ed{
	int dep,fa,maxxson,son,num,top;
}l[1000040];
int num,cnt;
int a[1000004];
int w[1000004];
int h[1000004];
int siz[1000004];
void add(int a,int b){
	z[++cnt].to=b;
	z[cnt].nxt=h[a];
	h[a]=cnt;
}
void Dfs(int x,int fa){
	siz[x]++;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			Dfs(y,x);
			siz[x]+=siz[y];
		}
	}
}
void dfs1(int x,int fa,int top){
	l[x].num=++num;
	l[x].top=top;
	w[num]=a[x];
	if(!l[x].maxxson) return ;
	else{
		dfs1(l[x].maxxson,x,top);
	}
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa||y==l[x].maxxson) continue;
		else{
			dfs1(y,x,y);
		}
	}
}
void build(int l,int r,int k){
	t[k].l=l;
	t[k].r=r;
	if(l==r){
		t[k].sum=w[l];
		t[k].lazy=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	t[k].sum=t[k*2].sum+t[k*2+1].sum; 
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep;
	l[l[x].maxxson].son=-1;
	l[x].son=1;
	for(int i=h[x];i;i=z[i].nxt){
		int to=z[i].to;
		if(to==fa) continue;
		dfs(to,x);
		l[x].son+=l[to].son;
		if(l[to].son>l[l[x].maxxson].son){
			l[x].maxxson=to;
			l[l[x].maxxson].son=l[to].son;
		}
	}
}
void lazzy(int k){
	if(t[k].lazy){
		t[k*2].sum+=(t[k*2].r-t[k*2].l+1)*t[k].lazy;
		t[k*2+1].sum+=(t[k*2+1].r-t[k*2+1].l+1)*t[k].lazy;
		t[k*2].lazy+=t[k].lazy;
		t[k*2+1].lazy+=t[k].lazy;
		t[k].lazy=0;
	}
}
void chan(int x,int p,int k){
	if(t[k].l==t[k].r){
		t[k].sum+=p;
		return ;
	}
	lazzy(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(x<=mid){
		chan(x,p,k*2);
	}
	else{
		chan(x,p,k*2+1); 
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
void change(int l,int r,int p,int k){
	if(t[k].l>=l&&t[k].r<=r){
		t[k].sum+=(t[k].r-t[k].l+1)*p;
		t[k].lazy+=p;
		return ;
	}
	lazzy(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(l<=mid){
		change(l,r,p,k*2);
	}
	if(r>mid){
		change(l,r,p,k*2+1);
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
int n,m;
void Chan(int x,int y){
	change(l[x].num,l[x].num+siz[x]-1,y,1);
}
int find_tree(int l,int r,int k){
	if(t[k].l>=l&&t[k].r<=r){
		return t[k].sum;
	}
	int sum=0;
	lazzy(k);
	int mid=(t[k].l+t[k].r)>>1;
	if(l<=mid){
		sum+=find_tree(l,r,k*2); 
	}
	if(r>mid){
		sum+=find_tree(l,r,k*2+1);
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
	return sum;
}
int find(int x){
	int ans=0;
	while(l[x].top!=1){
		int s=find_tree(l[l[x].top].num,l[x].num,1);
		ans+=s;
		x=l[l[x].top].fa;
	}
	ans+=find_tree(1,l[x].num,1);
	return ans;
}
signed main(){
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
	}
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%lld%lld",&a,&b);
		add(a,b);
		add(b,a);
	}
	l[0].dep=0;
	dfs(1,0);
	dfs1(1,0,1);
	Dfs(1,0);
	build(1,n,1);
	for(int i=1;i<=m;i++){
		int opt;
		scanf("%lld",&opt);
		if(opt==1){
			int x,p;
			scanf("%lld%lld",&x,&p);
			chan(l[x].num,p,1);
		}
		if(opt==2){
			int x,p;
			scanf("%lld%lld",&x,&p);
			Chan(x,p);
		}
		if(opt==3){
			int x;
			scanf("%lld",&x);
			printf("%lld\n",find(x));
		}
	}
}

P3258 [JLOI2014] 松鼠的新家

可以看我这篇 专栏

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
int cnt;
struct node{
	int to,nxt;
}z[10000004];
struct nod{
	int dep,fa,top,son,maxxson,num;
}l[10000003];
int h[10000004];
int d[10000004];
int a[10000004];
void add(int x,int y){
	z[++cnt].to=y;
	z[cnt].nxt=h[x];
	h[x]=cnt;
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			} 
		}
	}
}
int num;
void dfs1(int x,int fa,int top){
	l[x].num=++num;
	l[x].top=top;
	if(!l[x].maxxson) return ;
	else{
		dfs1(l[x].maxxson,x,top);
		for(int i=h[x];i;i=z[i].nxt){
			int y=z[i].to;
			if(y==fa||y==l[x].maxxson) continue;
			else{
				dfs1(y,x,y);
			}
		}
	}
}
int lca(int a,int b){
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep){
			swap(a,b);
		}
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	return a;
}
int ans;
void Dfs(int x,int fa){
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		Dfs(y,x);
		d[x]+=d[y];
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	l[0].dep=0;
	dfs(1,0);
	dfs1(1,0,1);
	for(int i=1;i<n;i++){
		int lcA=lca(a[i],a[i+1]);
		d[a[i]]++;
		d[a[i+1]]++;
		d[lcA]--;
		d[l[lcA].fa]--;
	}
	Dfs(1,0);
	for(int i=2;i<=n;i++){
		d[a[i]]--;
	}
	for(int i=1;i<=n;i++){
		printf("%d\n",d[i]);
	}
} 

P3384 【模板】重链剖分/树链剖分

名副其实的版子题

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct node{
	int to,nxt;
}z[N];
struct tree{
	int l,r,lazy,sum;
}t[4*N];
struct good{
	int w,fa,top,id,d,son,maxson;
}l[N];
int n,m,root,mod,ans;
int h[N];
int a[N];
int w[N];
int cnt,res;
void add(int x,int y){
	cnt++;
	z[cnt].to=y;
	z[cnt].nxt=h[x];
	h[x]=cnt;
}
void dfs1(int x,int fa,int dis){
	l[x].son=1;
	l[x].fa=fa;
	l[x].d=dis;
	l[l[x].maxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		dfs1(y,x,dis+1);
		l[x].son+=l[y].son;
		if(l[y].son>l[l[x].maxson].son) l[x].maxson=y,l[l[x].maxson].son=l[y].son;
	//	cout<<l[x].maxson<<" "<<l[l[x].maxson].son<<endl; 
	}
}
void dfs2(int x,int topf){
    l[x].id=++cnt;
    w[cnt]=a[x];
    l[x].top=topf;
    //cout<<l[x].top<<endl;
   // return ;
    if(!l[x].maxson)return;
    dfs2(l[x].maxson,topf);
    for(int i=h[x];i;i=z[i].nxt){
        int y=z[i].to;
        if(y==l[x].fa||y==l[x].maxson)continue;
        dfs2(y,y);
    }
}
void build(int l,int r,int p){
	t[p].l=l;
	t[p].r=r;
	if(l==r){
		t[p].sum=w[l];
		t[p].sum%=mod;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,p*2);
	build(mid+1,r,p*2+1);
	t[p].sum=t[p*2].sum+t[p*2+1].sum;
	t[p].sum%=mod;
//	cout<<"ok"<<endl;
}
void lazzy(int x){
	if(t[x].lazy){
		t[x*2].sum+=t[x].lazy*(t[x*2].r-t[x*2].l+1);
		t[x*2+1].sum+=t[x].lazy*(t[x*2+1].r-t[x*2+1].l+1);
		t[x*2].lazy+=t[x].lazy;
		t[x*2+1].lazy+=t[x].lazy;
		t[x*2].sum%=mod;
		t[x*2+1].sum%=mod;
		t[x*2+1].lazy%=mod;
		t[x*2].lazy%=mod; 
		t[x].lazy=0;
	}
//	cout<<"oK"<<endl;
}
int qury(int L,int R,int p){
	int res=0;
//	cout<<L<<" "<<R<<endl;
	if(t[p].l>=L&&t[p].r<=R) {
		return t[p].sum;
	}
	lazzy(p);
	int mid=t[p].l+t[p].r>>1;
	if(L<=mid){
		res+=qury(L,R,p*2);
	}
	if(R>mid){
		res+=qury(L,R,p*2+1);
	}
	//	cout<<"rrr"<<endl;	
	return res%mod;

}
void chan(int l,int r,int k,int p){
//	cout<<"ki"<<endl;
	if(t[p].l>=l&&t[p].r<=r){
		t[p].lazy+=k;
		t[p].sum+=k*(t[p].r-t[p].l+1);
		t[p].sum%=mod;
		t[p].lazy%=mod;
		return ;
	}
	lazzy(p);
	int mid=t[p].r+t[p].l>>1;
	if(l<=mid){
		chan(l,r,k,p*2);
	}
	if(r>mid){
		chan(l,r,k,p*2+1);
	}
	t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
//	cout<<"od"<<endl;
}
int find(int x,int y){


	int ans=0;
	while(l[x].top!=l[y].top){
		if(l[l[x].top].d<l[l[y].top].d){
			swap(x,y);
		}
	//	res=0;
		ans+=qury(l[l[x].top].id,l[x].id,1);
		ans=ans%mod;
		x=l[l[x].top].fa;
	}
	if(l[x].d>l[y].d) swap(x,y);

	ans+=qury(l[x].id,l[y].id,1);
	
	//	cout<<"Od"<<endl;
	return ans%mod;
}
void geng2(int x,int z){
	chan(l[x].id,l[x].id+l[x].son-1,z,1);
//	cout<<"OK"<<endl;
}
void geng(int x,int y,int z){
	
	z=z%mod;
	while(l[x].top!=l[y].top){
		if(l[l[x].top].d<l[l[y].top].d){
			swap(x,y);
		}
		chan(l[l[x].top].id,l[x].id,z,1);
		x=l[l[x].top].fa;
	}
	if(l[x].d>l[y].d){
		swap(x,y);
	}
	chan(l[x].id,l[y].id,z,1);
//	cout<<"OD"<<endl;
}
int find2(int x){
	ans=0;
	ans=qury(l[x].id,l[x].id+l[x].son-1,1);
//	cout<<"oD"<<endl;
	return ans%mod;
}
int main(){
	scanf("%d%d%d%d",&n,&m,&root,&mod);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		a[i]%=mod;
	}
	for(int i=1;i<=n-1;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x); 
	}
	dfs1(root,0,1);
	cnt=0;
	dfs2(root,root);
	build(1,n,1);
//	cout<<l[5].id<<" "<<l[5].son<<endl;
	for(int i=1;i<=m;i++){
		int opt;
		scanf("%d",&opt);
		if(opt==1){
			int x,y,z;
			scanf("%d%d%d",&x,&y,&z);
			geng(x,y,z);
		}
		if(opt==2){
			int x,y;
			scanf("%d%d",&x,&y);
			printf("%d\n",find(x,y));
		}
		if(opt==3){
			int x,z;
			scanf("%d%d",&x,&z);
			geng2(x,z);
		}
		if(opt==4){
			int x;
			scanf("%d",&x);
			printf("%d\n",find2(x));
		}
	}
}

P3833 [SHOI2012] 魔法树

  • 思路:
    由于是用 DFS 来编的号,所以同一子树的号码是连续的。
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int fa,maxxson,num,top,son,dep;
}l[10000003];
int n;
struct NODE{
	int to,nxt;
}z[10000003];
struct Tree{
	int l,r,sum,lazy;
}t[2000004];
int h[1000003];
int cnt;
int ans;
int ye[10000003];
int siz[1000033];
void add(int a,int b){
	cnt++;
	z[cnt].to=b;
	z[cnt].nxt=h[a];
	h[a]=cnt;
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep+1;
	l[l[x].maxxson].son=-1;
	l[x].son=1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		dfs(y,x);
		if(l[y].son>l[l[x].maxxson].son){
			l[x].maxxson=y;
			l[l[x].maxxson].son=l[y].son;
		}
	}
}
int num;
int w[10000003];
void lazzy(int k){
	if(t[k].lazy!=0){
		//cout<<"H"<<endl;
		t[k*2].sum+=t[k].lazy*(t[k*2].r-t[k*2].l+1);
		t[k*2+1].sum+=t[k].lazy*(t[k*2+1].r-t[k*2+1].l+1);
		t[k*2].lazy+=t[k].lazy;
		t[k*2+1].lazy+=t[k].lazy; 
		t[k].lazy=0;
	}
}
void dfs1(int x,int fa,int Top){
	l[x].top=Top;
	l[x].num=num++;
	if(!l[x].maxxson) return ;
	dfs1(l[x].maxxson,x,Top);
	for(int i=h[x];i;i=z[i].nxt){
		int to=z[i].to;
		if(to==fa||to==l[x].maxxson) continue;
		dfs1(to,x,to);
	}
}
void add_tree(int l,int r,int p,int k){
	if(t[k].l>=l&&t[k].r<=r){
		t[k].sum+=(t[k].r-t[k].l+1)*p;
		t[k].lazy+=p;
		//	cout<<"K"<<k<<" "<<t[k].lazy<<endl; 
		return ;
	}
	lazzy(k);
	int mid=t[k].l+t[k].r>>1;
	if(l<=mid){
		add_tree(l,r,p,k*2);
	}
	if(r>mid){
		add_tree(l,r,p,k*2+1);
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
void addd(int a,int b,int p){
	//cout<<"P "<<p<<endl;
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep){
			swap(a,b);
		}
		add_tree(l[l[a].top].num,l[a].num,p,1);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	add_tree(l[a].num,l[b].num,p,1);
}
int Sum_tree(int l,int r,int k){
	if(t[k].l>=l&&t[k].r<=r){
		return t[k].sum;
	}
	lazzy(k);
	int ans=0;
	int mid=t[k].l+t[k].r>>1;
	if(l<=mid){
		ans+=Sum_tree(l,r,k*2);
	} 
	if(r>mid){
		ans+=Sum_tree(l,r,k*2+1);
	}
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
	return ans;
}
void find(int a){
	//	cout<<a<<" "<<y<<endl;
	ans=Sum_tree(l[a].num,l[a].num+siz[a]-1,1);
}
void build(int l,int r,int k){
	t[k].l=l;
	t[k].r=r;
	if(l==r){
		t[k].sum=0;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
	t[k].sum=t[k*2].sum+t[k*2+1].sum;
}
void dfs2(int x,int fa){
	siz[x]++;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs2(y,x);
			siz[x]+=siz[y];
		}
	}
	//cout<<"X "<<x<<" "<<siz[x]<<endl;
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%lld%lld",&a,&b);
		add(a,b);
	}
	l[0].dep=0;
	dfs(0,0);
	dfs2(0,0);
	dfs1(0,0,0);
	build(0,n-1,1);
	int q;
	scanf("%lld",&q);
	for(int i=1;i<=q;i++){
		char a;
		cin>>a;
		if(a=='A'){
			int u,v,d;
			scanf("%lld%lld%lld",&u,&v,&d);
			addd(u,v,d);
		}
		else{
			ans=0;
			int u;
			scanf("%lld",&u);
			find(u);
			cout<<ans<<endl;
		}
	}
}

P4092 [HEOI2016/TJOI2016] 树

  • 思路:
    并查集就够了
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int opt[100003];
int n,q;
int fa[100003];
char Opt[100003];
int OPT[100030];
int ans[100003]; 
int find(int x){
//	cout<<x<<endl;
	if(opt[x]>0) return x;
	else return fa[x]=find(fa[x]);
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		fa[b]=a;
	}
	opt[1]=1; 
	for(int i=1;i<=q;i++){
		scanf("%s%d",&Opt[i],&OPT[i]);
		//Opt[i]=s[0]; 
	//	cout<<Opt[i]<<endl;
		if(Opt[i]=='C'){
			//cout<<" "<<OPT[i]<<" "<<opt[OPT[i]]<<endl;
			opt[OPT[i]]++;
		} 
	}
//	return 0;
//	for(int i=1;i<=n;i++) printf("%d ",opt[i]);
	for(int i=q;i>=1;i--){
	//	cout<<" "<<OPT[i]<<" "<<opt[OPT[i]]<<endl;
		if(Opt[i]=='C') opt[OPT[i]]--;
		else{
		   ans[i]=find(OPT[i]);
		}
	}
	for(int i=1;i<=q;i++){
		if(Opt[i]=='Q') printf("%d\n",ans[i]);
	}
} 

P4114 Qtree1

边权转点权

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
struct NODE{
	int to,nxt,w;
}z[200004];
struct edge{
	int fa,maxxson,son,dep,top;
}l[100004];
struct Tree{
	int l,r,sum,maxx;
}t[400003];
struct node{
	int a,b;
}b[200004];
int h[100004];
int cnt;
void add(int a,int b,int c){
	z[++cnt].to=b;
	z[cnt].nxt=h[a];
	z[cnt].w=c;
	h[a]=cnt;
}
int num;
int ww[1000004],val[1000004],id[1000004];
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[l[x].maxxson ].son=-1;
	for(int i=h[x];i;i=z[i].nxt ){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			ww[y]=z[i].w;
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson ].son){
				l[x].maxxson=y;
				l[l[x].maxxson ].son=l[y].son;
			}
		}
	}
}
void DFS(int x,int top){
	l[x].top=top;
	id[x]=++num;
	val[num]=ww[x];
	//cout<<"NUM "<<num<<" "<<x<<" "<<val[num]<<endl;
	if(!l[x].maxxson ) return ;
	else{
		DFS(l[x].maxxson,top);
		for(int i=h[x];i;i=z[i].nxt ){
			int y=z[i].to;
			if(y==l[x].fa||y==l[x].maxxson ) continue;
			else{
				DFS(y,y);
			}
		}
	}
}
void build(int l,int r,int x){
	t[x].l=l;
	t[x].r=r;
	if(l==r){
	//	cout<<l<<" "<<t[x].maxx<<endl;
		t[x].maxx=val[l];
	//	cout<<l<<" "<<t[x].maxx<<endl;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,x*2);
	build(mid+1,r,x*2+1);
	t[x].maxx=max(t[x*2].maxx,t[x*2+1].maxx );
}
void chan(int l,int k,int x){
	if(t[x].l==t[x].r ){
		t[x].maxx=k;
		return ;
	}
	int mid=t[x].l+t[x].r>>1;
	if(l<=mid){
		chan(l,k,x*2);
	}
	else{
		chan(l,k,x*2+1); 
	}
	t[x].maxx=max(t[x*2].maxx,t[x*2+1].maxx );
}
int query_tree(int l,int r,int x){
	if(t[x].l>=l&&t[x].r<=r){
	//	cout<<t[x].l<<" "<<t[x].r<<endl;
		return t[x].maxx;
	}
	int maxx=-1e8,mid=t[x].l+t[x].r>>1;
	if(l<=mid){
		maxx=max(maxx,query_tree(l,r,x*2));
	}
	if(r>mid){
		maxx=max(maxx,query_tree(l,r,x*2+1));
	}
	return maxx;
}
int query(int a,int b){
	int maxx=-1e8;
	while(l[a].top!=l[b].top){
		if(l[l[a].top ].dep<l[l[b].top].dep ) swap(a,b);
		maxx=max(maxx,query_tree(id[l[a].top],id[a],1));
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
//	cout<<id[a]+1<<" "<<id[b]<<endl;
	maxx=max(maxx,query_tree(id[a]+1,id[b],1));
	return maxx;
}
int main(){
	cin>>n;
	for(int i=1;i<n;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
		b[i].a=u;
		b[i].b=v;
	}
	dfs(1,0);
	DFS(1,1);
	build(1,n,1);
	string s;
	while(cin>>s){
		if(s=="DONE") break;
		else{
			int x,y;
			scanf("%d%d",&x,&y);
			if(s=="CHANGE"){
				if(l[b[x].a].dep<l[b[x].b].dep) swap(b[x].a,b[x].b);
				chan(id[b[x].a],y,1);
			}
			else{
				if(x==y) cout<<"0\n";
				else cout<<query(x,y)<<endl;
			}
		}
	}
}

P4116 Qtree3

点击查看代码
#include<bits/stdc++.h>
using namespace std;
struct node{
	int to,nxt;
}z[1000004];
struct tree{
	int l,r,minn,val;
}t[1000004];
struct nnn{
	int top,fa,num,maxxson,son,dep;
}l[1000004];
int n,q;
int cnt;
int h[1000004];
void add(int x,int y){
	cnt++;
	z[cnt].to=y;
	z[cnt].nxt=h[x];
	h[x]=cnt;
}
void dfs(int x,int fa){
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[x].fa=fa;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			}
		}
	}
}
int num;
int id[10000003];
void dfss(int x,int fa,int top){
	l[x].top=top;
	l[x].num=++num;
	id[num]=x;
	if(!l[x].maxxson) return ;
	dfss(l[x].maxxson,x,top);
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa||y==l[x].maxxson) continue;
		else{
			dfss(y,x,y);
		}
	}
}
void build(int l,int r,int k){
	t[k].l=l;
	t[k].r=r;
	t[k].minn=1e9;
	if(l==r){
		t[k].val=0;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,k*2);
	build(mid+1,r,k*2+1);
}
void chan(int x,int k){
	if(t[k].l==t[k].r){
		if(t[k].val==1){
			t[k].val=0;
			t[k].minn=1e9;
		}
		else{
			t[k].val=1;
			t[k].minn=id[x];
		}
		return ;
	}
	int mid=t[k].l+t[k].r>>1;
	if(x<=mid){
		chan(x,k*2);
	}
	else{
		chan(x,k*2+1);
	}
	if(t[k*2].minn==1e9&&t[k*2+1].minn!=1e9) t[k].minn=t[k*2+1].minn;
	if(t[k*2].minn!=1e9&&t[k*2+1].minn==1e9) t[k].minn=t[k*2].minn;
	if(t[k*2].minn==1e9&&t[k*2+1].minn==1e9) t[k].minn=1e9;
	if(t[k*2].minn!=1e9&&t[k*2+1].minn!=1e9){
		if(l[t[k*2].minn].dep<l[t[k*2+1].minn].dep){
			t[k].minn=t[k*2].minn;
		}
		else{
			t[k].minn=t[k*2+1].minn;
		}
	}
}
int find(int L,int r,int k){
	if(t[k].l>=L&&t[k].r<=r){
		return t[k].minn;
	}
	int mid=t[k].l+t[k].r>>1;
	int ans=1e9;
	if(L<=mid){
		ans=find(L,r,k*2);
	}
	if(r>mid){
		int tt=find(L,r,k*2+1);
		if(ans==1e9) ans=tt;
		else{
			if(tt!=1e9&&l[ans].dep>l[tt].dep){
				ans=tt;
			}
		} 
	}
	return ans;
}
void Find(int x){
	int ans=1e9;
	while(l[x].top!=1){
	//	cout<<x<<" "<<l[x].top<<endl;
		int _=find(l[l[x].top].num,l[x].num,1);
		if(_!=1e9){
			if(ans==1e9) ans=_;
			else{
				if(l[_].dep<l[ans].dep){
					ans=_;
				}
			}
		}
		x=l[l[x].top].fa;
	}
	int _=find(l[1].num,l[x].num,1);
	if(_!=1e9){
		if(ans==1e9) ans=_;
		else{
			if(l[_].dep<l[ans].dep){
				ans=_;
			}
		}	
	}
	if(ans==1e9) ans=-1;
	printf("%d\n",ans);
}
int main(){
	scanf("%d%d",&n,&q);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	l[0].dep=0;
	dfs(1,0);
	dfss(1,0,1);
	build(1,n,1);
	while(q--){
		int opt;
		scanf("%d",&opt);
		if(opt==0){
			int x;
			scanf("%d",&x);
			chan(l[x].num,1);
		}
		else{
			int x;
			scanf("%d",&x);
			Find(x);
		}
	}
}

P4281 [AHOI2008] 紧急集合 / 聚会

  • 思路:
    求出两两的 LCA ,取深度最大的那个。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
struct node{
	int to,nxt;
}z[5000004];
int h[5000004];
struct nd{
	int top,fa,maxxson,son,dep;
}l[5000004];
int cnt;
void add(int a,int b){
	z[++cnt].to=b;
	z[cnt].nxt=h[a];
	h[a]=cnt;
}
void dfs(int x,int fa){
	l[x].fa=fa;
	l[x].son=1;
	l[l[x].maxxson].son=-1;
	l[x].dep=l[l[x].fa].dep+1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son; 
			}
		}
	}
} 
void DFS(int x,int top){
	l[x].top=top;
	if(!l[x].maxxson) return ;
	DFS(l[x].maxxson,top);
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==l[x].fa||y==l[x].maxxson) continue;
		else{
			DFS(y,y);
		}
	}
}
int lca(int a,int b){
	while(l[a].top!=l[b].top){
		if(l[l[a].top].dep<l[l[b].top].dep) swap(a,b);
		a=l[l[a].top].fa;
	}
	if(l[a].dep>l[b].dep) swap(a,b);
	return a;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<n;i++){
		int a,b;
		scanf("%d%d",&a,&b);
		add(a,b);
		add(b,a);
	}
	dfs(1,0);
	DFS(1,1);
	for(int i=1;i<=m;i++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		int LCA;
		int lca1=lca(a,b);
		int lca2=lca(a,c);
		int lca3=lca(b,c);
		int maxx=max(max(l[lca1].dep,l[lca2].dep),l[lca3].dep);
		if(maxx==l[lca1].dep) {
			LCA=lca(lca1,c);
			printf("%d %d\n",lca1,l[a].dep+l[b].dep-l[lca1].dep+l[c].dep-2*l[LCA].dep);
			continue;
		}
		if(maxx==l[lca2].dep){
			LCA=lca(lca2,b);
			printf("%d %d\n",lca2,l[a].dep+l[c].dep-l[lca2].dep+l[b].dep-2*l[LCA].dep);
			continue;
		}
		if(maxx==l[lca3].dep){
			LCA=lca(lca3,a);
			printf("%d %d\n",lca3,l[b].dep+l[c].dep-l[lca3].dep+l[a].dep-2*l[LCA].dep);
			continue;
		}
	}
}

P4315 月下“毛景树”

一如既往的边权转点权

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
struct tree{
	int l,r,sum,lazy,Lazy,maxx;
}t[10000004];
struct node{
	int to,nxt,w;
}z[10000004];
struct no{
	int dep,num,top,fa,son,maxxson;
}l[10000004];
int cnt;
int h[10000400];
int val[10000040];
int id[10000040];
void add(int x,int y,int w){
	++cnt;
	z[cnt].to=y;
	z[cnt].nxt=h[x];
	z[cnt].w=w;
	h[x]=cnt;
}
void dfs(int x,int fa){
	l[x].dep=l[fa].dep+1;
	l[x].son=1;
	l[x].fa=fa;
	l[l[x].maxxson].son=-1;
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa) continue;
		else{
			dfs(y,x);
			l[x].son+=l[y].son;
			if(l[y].son>l[l[x].maxxson].son){
				l[x].maxxson=y;
				l[l[x].maxxson].son=l[y].son;
			}
		}
	}
}
int num;
int w[10000040];
void dfss(int x,int fa,int top){
	l[x].top=top;
	l[x].num=++num;
	w[num]=val[x];
	//cout<<num<<" "<<val[x]<<" "<<x<<endl;
	if(!l[x].maxxson) return ;
	dfss(l[x].maxxson,x,top);
	for(int i=h[x];i;i=z[i].nxt){
		int y=z[i].to;
		if(y==fa||y==l[x].maxxson) continue;
		else{
			dfss(y,x,y);
		}
	}
}
void lazzy(int k){
	if(t[k].lazy!=-1){
		t[k*2].maxx=t[k].lazy;
		t[k*2+1].maxx=t[k].lazy;
		t[k*2].lazy=t[k*2+1].lazy=t[k].lazy;
		t[k*2].Lazy=t[k*2+1].Lazy=0;
		t[k].lazy=-1;
	}
	if(t[k].Lazy){
		t[k*2].maxx+=t[k].Lazy;
		t[k*2+1].maxx+=t[k].Lazy;
		t[k*2].Lazy+=t[k].Lazy;
		t[k*2+1].Lazy+=t[k].Lazy;
		t[k].Lazy=0;
	}
}
void build(int L,int r,int k){
	t[k].l=L;
	t[k].r=r;
	t[k].lazy=-1;
	t[k].Lazy=0;
	if(L==r){
		t[k].maxx=w[L];
		return ;
	}
	int mid=L+r>>1;
	build(L,mid,k*2);
	build(mid+1,r,k*2+1);
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
	//cout<<k<<" "<<t[k].maxx<<endl;
}
void chan(int x,int p,int k){
	if(t[k].l==t[k].r){
		t[k].maxx=p;
		return ;
	}
	lazzy(k);
	int mid=t[k].l+t[k].r>>1;
	if(x<=mid){
		chan(x,p,k*2);
	}
	else{
		chan(x,p,k*2+1);
	}
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
}
struct edge{
	int from,to,w;
}e[1000004];
int tot;
void Chan_tree(int l,int r,int p,int k){
	if(t[k].l>=l&&t[k].r<=r){
		t[k].maxx=p;
		t[k].lazy=p;
		t[k].Lazy=0;
		return ;
	}
	lazzy(k);
	int mid=t[k].l+t[k].r>>1;
	if(l<=mid){
		Chan_tree(l,r,p,k*2);
	}
	if(r>mid){
		Chan_tree(l,r,p,k*2+1);
	}
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
}
void Chan(int u,int v,int w){
//	u=id[l[u].num+1];
	while(l[u].top!=l[v].top){
		if(l[l[u].top].dep<l[l[v].top].dep){
			swap(u,v);
		}
		Chan_tree(l[l[u].top].num,l[u].num,w,1);
		u=l[l[u].top].fa;
	}
	if(l[u].dep>l[v].dep) swap(u,v);
	Chan_tree(l[u].num+1,l[v].num,w,1); 
}
void add_tree(int l,int r,int p,int k){
	if(t[k].l>=l&&t[k].r<=r){
		t[k].maxx+=p;
		t[k].Lazy+=p;
		return ;
	}
	lazzy(k);
	int mid=t[k].l+t[k].r>>1;
	if(l<=mid){
		add_tree(l,r,p,k*2);
	}
	if(r>mid){
		add_tree(l,r,p,k*2+1);
	}
	t[k].maxx=max(t[k*2].maxx,t[k*2+1].maxx);
}
void ADD(int u,int v,int w){
//	u=id[l[u].num+1];
	while(l[u].top!=l[v].top){
		if(l[l[u].top].dep<l[l[v].top].dep){
			swap(u,v);
		}
		add_tree(l[l[u].top].num,l[u].num,w,1);
		u=l[l[u].top].fa;
	}
	if(l[u].dep>l[v].dep) swap(u,v);
	add_tree(l[u].num+1,l[v].num,w,1); 
}
int find(int l,int r,int k){
	if(t[k].l>=l&&t[k].r<=r){
		return t[k].maxx;
	}
	lazzy(k);
	int maxx=-1e9;
	int mid=t[k].l+t[k].r>>1;
	if(l<=mid){
		maxx=max(maxx,find(l,r,k*2));
	}
	if(r>mid){
		maxx=max(maxx,find(l,r,k*2+1));
	}
	return maxx;
}
void Find(int u,int v){
//	u=id[l[u].num+1];
	int maxx=-1e9;
	while(l[u].top!=l[v].top){
		if(l[l[u].top].dep<l[l[v].top].dep){
			swap(u,v);
		}
		maxx=max(maxx,find(l[l[u].top].num,l[u].num,1));
		//cout<<l[l[u].top].num<<" "<<l[u].num<<" "<<u<<" "<<v<<endl;
		u=l[l[u].top].fa;
	}
	if(l[u].dep>l[v].dep) swap(u,v);
	maxx=max(maxx,find(l[u].num+1,l[v].num,1));
//	cout<<l[u].num+1<<" "<<l[v].num<<endl;
	printf("%d\n",maxx);
}
int main(){
	//freopen("P4315_1.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
		e[++tot]={u,v,w};
	}
	l[0].dep=0;
	dfs(1,0);
	num=0;
	for(int i=1;i<=tot;i++){
		if(l[e[i].from].dep>l[e[i].to].dep){
			val[e[i].from]=e[i].w;
		}
		else{
			val[e[i].to]=e[i].w;
		}
	}
	dfss(1,0,1);
	build(1,n,1);
	for(int i=1;i<=tot;i++){
		if(l[e[i].from].fa==e[i].to){
			swap(e[i].from,e[i].to);
		}
	}
	string opt;
	while(cin>>opt){
		if(opt=="Stop") break;
		if(opt=="Change"){
			int x,w;
			scanf("%d%d",&x,&w);
			x=e[x].to;
			chan(l[x].num,w,1);
		}
		if(opt=="Cover"){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			if(u==v) continue;
			Chan(u,v,w);
		}
		if(opt=="Add"){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			if(u==v) continue;
			ADD(u,v,w);
		}
		if(opt=="Max"){
			int u,v;
			scanf("%d%d",&u,&v);
			Find(u,v);
		}
	}
}
posted @   yueyan_WZF  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示