ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

「USACO11DEC」Grass Planting G 题解 (树链剖分)

2022-02-17 22:02:32  阅读:147  来源: 互联网

标签:Planting 剖分 int 题解 top tr fa dep id


题目简介

给出一棵 \(N\) 个节点的树,有 \(M\) 个操作,操作为将一条路径上的边权加一或询问某条边的权值。

分析

点差分与边差分的区别是:点差分计入 \(lca\) ,边差分不计 \(lca\)。

模板树链剖分是对点统计,类似点差分。

本题是对边统计,只需要去掉 \(lca\) 的计算即可。

\(AC\ Code\)

如觉怪异,请见谅。

#include<cstdio>
#include<iostream>
using namespace std;
int read(){
	int x=0;
	char ch=getchar();
	while(ch<'0'||ch>'9')ch=getchar();
	while(ch>='0'&&ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x;
}
const int Maxn=1e5+5;
const int Inf=0x3f3f3f3f;
namespace A{
	struct Adjacency_List{
		int nxt,t;
	}tr[Maxn<<1];
	int h[Maxn];
	int tot;
	void Add(int x,int y){
		tr[++tot].nxt=h[x];
		tr[tot].t=y;
		h[x]=tot;
	}
}
namespace B{
	struct Segment_Tree{
		int l,r;
		int val;
		int lazy;
	}tr[Maxn<<2];
	inline int ls(int k){return k<<1;}
	inline int rs(int k){return k<<1|1;}
	inline int len(int k){return tr[k].r-tr[k].l+1;}	
	inline void push_up(int k){
		tr[k].val=tr[ls(k)].val+tr[rs(k)].val;
	}
	inline void push_down(int k){
		if(!tr[k].lazy)return ;
		tr[ls(k)].val+=len(ls(k))*tr[k].lazy;
		tr[ls(k)].lazy+=tr[k].lazy;
		tr[rs(k)].val+=len(rs(k))*tr[k].lazy;
		tr[rs(k)].lazy+=tr[k].lazy;
		tr[k].lazy=0;
	}
	void build(int k,int l,int r){
		tr[k].l=l,tr[k].r=r;
		if(l==r)return;
		int mid=(l+r)>>1;
		build(ls(k),l,mid);
		build(rs(k),mid+1,r);
	}
	int query(int k,int ql,int qr){
//		printf("(%d) [%d, %d] = %d\n",k,tr[k].l,tr[k].r,tr[k].val);
		if(ql<=tr[k].l&&tr[k].r<=qr)
			return tr[k].val;
		push_down(k);
		int mid=(tr[k].l+tr[k].r)>>1;
		int ret=0;
		if(ql<=mid)ret+=query(ls(k),ql,qr);
		if(qr>mid)ret+=query(rs(k),ql,qr);
		return ret;
	}
	void modifit(int k,int ql,int qr,int d){
		if(ql<=tr[k].l&&tr[k].r<=qr){
			tr[k].val+=len(k)*d;
			tr[k].lazy+=d;
//			printf("(%d) [%d, %d] = %d\n",k,tr[k].l,tr[k].r,tr[k].val);
			return ;
		}
		push_down(k);
		int mid=(tr[k].l+tr[k].r)>>1;
		if(ql<=mid)modifit(ls(k),ql,qr,d);
		if(qr>mid)modifit(rs(k),ql,qr,d);
		push_up(k);
//		printf("(%d) [%d, %d] = %d\n",k,tr[k].l,tr[k].r,tr[k].val);
	}
}
struct node{
	int id;
	int fa,son;
	int dep,top;
	int sz;
}p[Maxn];
int tot;
void dfs1(int x,int fa){
	p[x].fa=fa;
	p[x].dep=p[fa].dep+1;
	p[x].sz=1;
	int k=-Inf;
	for(int i=A::h[x];i;i=A::tr[i].nxt){
		int y=A::tr[i].t;
		if(y==fa)continue;
		dfs1(y,x);
		p[x].sz+=p[y].sz;
		if(p[y].sz>k){
			k=p[y].sz;
			p[x].son=y;
		}
	}
}
void dfs2(int x,int fa){
	p[x].id=++tot;
	if(p[x].son){
		int y=p[x].son;
		p[y].top=p[x].top;
		dfs2(y,x);
	}
	for(int i=A::h[x];i;i=A::tr[i].nxt){
		int y=A::tr[i].t;
		if(y==fa)continue;
		if(y==p[x].son)continue;
		p[y].top=y;
		dfs2(y,x);
	}
}
void P(int x,int y){
	while(p[x].top!=p[y].top){
		if(p[p[x].top].dep<p[p[y].top].dep)swap(x,y);
//		printf("In P : %d %d -> %d %d\n",p[x].top,x,p[p[x].top].id,p[x].id);
//		printf("In P : x = %d, y = %d\n",x,y);
		B::modifit(1,p[p[x].top].id,p[x].id,1);
		x=p[p[x].top].fa;
	}
	if(p[x].dep>p[y].dep)swap(x,y);
//	printf("In P : %d %d -> %d (%d) %d\n",x,y,p[x].id+1,p[x].id,p[y].id);
	B::modifit(1,p[x].id+1,p[y].id,1);
}
int Q(int x,int y){
	int ret=0;
	while(p[x].top!=p[y].top){
		if(p[p[x].top].dep<p[p[y].top].dep)swap(x,y);
//		printf("In Q : %d %d -> %d %d\n",p[x].top,x,p[p[x].top].id,p[x].id);
		ret+=B::query(1,p[p[x].top].id,p[x].id);
		x=p[p[x].top].fa;
	}
	if(p[x].dep>p[y].dep)swap(x,y);
//	printf("In Q : %d %d -> %d (%d) %d\n",x,y,p[x].id+1,p[x].id,p[y].id);
	ret+=B::query(1,p[x].id+1,p[y].id);
	return ret;
}
int main(){
	int n=read();
	int m=read();
	for(int i=1;i<n;i++){
		int x=read();
		int y=read();
		A::Add(x,y);
		A::Add(y,x);
	}
	p[1].top=1;
	dfs1(1,0);
	dfs2(1,0);
	B::build(1,1,n);
	while(m--){
		char str[2];
		scanf("%s",str);
		int x=read(),y=read();
		if(str[0]=='P')P(x,y);
		else printf("%d\n",Q(x,y));
	}
	return 0;
}

$$-----EOF-----$$

标签:Planting,剖分,int,题解,top,tr,fa,dep,id
来源: https://www.cnblogs.com/wintersunny/p/15906577.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有