BZOJ1103

BZOJ1103

传送门


题意

给定一棵树,根为1,要求支持两个操作
\(1、将点u到点v的路径上的边权置为0\)
\(2、查询点1到点u的路径边权和\)


做法

这显然是个差分/线段树/树状数组的题,但是不喜欢拿辅助数组维护\(bit\)的题主还是想写线段树,于是就用的树剖套线段树


代码

#include<bits/stdc++.h>
#define lc root<<1
#define rc root<<1|1
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define rg register
using namespace std;
const int maxn=250010;
struct Edge{int v,next;}edge[maxn<<1];
int head[maxn],father[maxn],deep[maxn],size[maxn],son[maxn],num[maxn],top[maxn],line[maxn],dis[maxn];
int lazy[maxn<<2],sum[maxn<<2];
int n,cnt=0,tot=0;
inline void addEdge(int u,int v){edge[++cnt]=(Edge){v,head[u]};head[u]=cnt;}
inline void dfs(int u,int fa){
	size[u]=1;
	for (rg int i=head[u];i;i=edge[i].next){
		int v=edge[i].v;
		if (v==fa) continue;
		father[v]=u;deep[v]=deep[u]+1;
		dfs(v,u);
		size[u]+=size[v];
		if (size[v]>size[son[u]]) son[u]=v;
	}
}

inline void dfs2(int u,int t){
	top[u]=t;num[u]=++tot;line[tot]=u;
	if (!son[u]) return;
	dfs2(son[u],t);
	for (rg int i=head[u];i;i=edge[i].next)
		if (edge[i].v!=father[u] && edge[i].v!=son[u]) dfs2(edge[i].v,edge[i].v);
}

inline int read(){int x=0,f=1;char ch=getchar();while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0' && ch<='9'){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}return x*f;}

inline void pushdown(int root,int l,int r){
	if (!lazy[root]) return;
	lazy[lc]=lazy[rc]=1;
	int mid=l+r>>1;
	sum[lc]=sum[rc]=lazy[root]=0;
}

inline void pushup(int root){sum[root]=sum[lc]+sum[rc];}

inline void build(int l,int r,int root){
	lazy[root]=0;
	if (l==r) {sum[root]=dis[line[l]];return;}
	int mid=l+r>>1;
	build(lson);build(rson);
	pushup(root);
}

inline void update(int L,int R,int l,int r,int root){
	if (l>=L && r<=R){
		sum[root]=0;
		lazy[root]=1;
		return;
	}
	pushdown(root,l,r);
	int mid=l+r>>1;
	if (L<=mid) update(L,R,lson);
	if (mid<R) update(L,R,rson);
	pushup(root);
}

inline int query(int L,int R,int l,int r,int root){
	if (l>=L && r<=R) return sum[root];
	pushdown(root,l,r);
	int mid=l+r>>1,ans=0;
	if (L<=mid) ans+=query(L,R,lson);
	if (R>mid)  ans+=query(L,R,rson);
	return ans;
}

inline void change(int u,int v){
	while (top[u]!=top[v]){
		if (deep[top[u]]<deep[top[v]]) swap(u,v);
		update(num[top[u]],num[u],1,n,1);
		u=father[top[u]];
	}
	if (deep[u]>deep[v]) swap(u,v);
	update(num[u]+1,num[v],1,n,1);
}

inline int getsum(int u,int v){
	int ans=0;
	while (top[u]!=top[v]){
		if (deep[top[u]]<deep[top[v]]) swap(u,v);
		ans+=query(num[top[u]],num[u],1,n,1);
		u=father[top[u]];
	}
	if (u==v) return ans;
	if (deep[u]>deep[v]) swap(u,v);
	ans+=query(num[u]+1,num[v],1,n,1);
	return ans;
}

int main(){
	n=read();
	for (rg int i=1;i<n;i++) {
		int u=read(),v=read();
		addEdge(u,v);addEdge(v,u);
		if (u>v) dis[u]++;else dis[v]++;
	}
	dfs(1,0);dfs2(1,1);
	build(1,n,1);
	int q=read()+n-1;
	while (q--){
		char ch=getchar();int x=read(),y;
		if (ch=='A') y=read(),change(x,y);
		else printf("%d\n",getsum(1,x));
	}
	return 0;
}
posted @ 2018-08-11 18:15  CYW_lyr  阅读(187)  评论(0编辑  收藏  举报