【BZOJ 1103】大都市【dfs序上建立树状数组、维护路径前缀和】

题意:

一颗包含 n n 个节点的树,每条边初始权值为 1 1 。支持两个操作,第一个操作将某一条边的权值变为 0 0 ,第二个操作询问从树根到节点 y y 的路径上有多少条权值为 1 1 的边。


思路:

这题对于树链剖分来说是一道裸题,但没必要。由于只求从根节点到节点 x x 上经过的所有边中有几条非 0 0 边,因此我们可以考虑一下维护前缀和。

首先我们可以发现点 A A 与它子树中所有节点的 d f s dfs 是连续的,假设区域 M M 内的点都是 A A 子树中的点,而 B B 不是。则我们现在将边权压到每条边上深度更深的点上,因此若点 A A 的权值为 1 1 ,则对于区域 M M 中的点来说,其到根节点路径上非 0 0 边需要 + 1 +1 ,而对于点B及其之后的点来说,是没有影响的。因此我们现在将这题转化为用树状数组求前缀和。

因此点 A A 如果 + 1 +1 ,我们需要在树状数组中将A点 + 1 +1 ,然后在B点 1 -1 ,这样B点及之后的点求前缀和时,答案才不会变。
在这里插入图片描述


代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define rep(i,a,b) for(int i = a; i <= b; i++)
#define LOG1(x1,x2) cout << x1 << ": " << x2 << endl;
#define LOG2(x1,x2,y1,y2) cout << x1 << ": " << x2 << " , " << y1 << ": " << y2 << endl;
typedef long long ll;
typedef double db;
const db EPS = 1e-9;
using namespace std;
const int N = 250000+1000;

int n,m,tot,head[N],fa[N],size[N],d[N],id[N],cnt,c[N];
struct Edge { int to,next; } e[2*N];

int low_bit(int x) { return x&(-x); }
void update(int x,int y) { for(; x <= n; x+=low_bit(x)) c[x] += y; }
void init() { tot = 1; memset(head,0,sizeof head); }
void add(int x, int y){ e[++tot].to = y, e[tot].next = head[x], head[x] = tot; }
int ask(int x){
	int ans = 0;
	for(;x;x-=low_bit(x)) ans += c[x];
	return ans;
}
void dfs(int x){
	id[x] = ++cnt, d[x] = d[fa[x]]+1, size[x] = 1;
	for(int i = head[x]; i; i = e[i].next){
		int y = e[i].to; 
		if(y == fa[x]) continue;
		fa[y] = x;
		dfs(y); size[x] += size[y];
	}
}
int main()
{
	scanf("%d",&n); init();
	rep(i,1,n-1){
		int x,y; scanf("%d%d",&x,&y);
		add(x,y), add(y,x);
	}
	scanf("%d",&m); cnt = 0, d[0] = 0, fa[1] = 0, dfs(1);
	rep(i,2,n) update(id[i],1),update(id[i]+size[i],-1);
	rep(i,1,n+m-1){
		char op[10]; int x,y;
		scanf("%s",op);
		if(op[0] == 'W'){
			scanf("%d",&x);
			printf("%d\n",ask(id[x]));
		}	
		else{
			scanf("%d%d",&x,&y);
			if(d[x] < d[y]) x = y;
			update(id[x],-1);
			update(id[x]+size[x],1);
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41552508/article/details/88613705