BZOJ1103 POI2007 大都市

这题目的意思大致就是本来有一棵所有边的权都是1的树、然后经过若干次操作把所有边的权值都变成0、中间会让你求根到一个点的权值和、

本来想过树链剖分、后来看看数据范围和如此弱的操作又感觉不是、、

然后分析一下、、这题就是快速求一个链上的数字和、、比如我们现在考虑根、就是相当于把根的所有子孙权值和剪掉这个儿子之外的所有儿子的子孙权值和、、

也就是说、每个点的权值只在它和它的子孙上有效、、

于是、、想到了DFS序、、每当访问到一个点、就在对应时间戳的位置+1、离开的时候在对应时间戳-1、

抹杀的时候就把两个时间戳都刷成0就好了、、

至于询问、、求个前缀和BIT大家都懂、、

 

Code:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>

#define lowbit(x) (x&(-x))

using namespace std;

int n,m,a,b,tt=0,r=0;
int fa[250010],num[500010],f1[250010],f2[250010];
int g[250010],e[250010],t[500010],next[500010];
char ch;

void add(int x,int d){
	while	(x<=2*n){
		num[x]+=d;
		x+=lowbit(x);
	}
}

int cnt(int x){
	int cur=0;
	while	(x){
		cur+=num[x];
		x-=lowbit(x);
	}
	return	cur;
}

void dfs(int cur){
	++tt;f1[cur]=tt;add(tt,1);
	for	(int u=g[cur];u;u=next[u])
		if	(fa[cur]!=t[u]){
			fa[t[u]]=cur;
			dfs(t[u]);
		}
	++tt;f2[cur]=tt;add(tt,-1);
}

void addedge(int a,int b){
	t[++r]=b;
	if	(g[a])	{next[e[a]]=r;e[a]=r;}
	else	g[a]=e[a]=r;
}

int main(){
	scanf("%d",&n);
	for	(int i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		addedge(a,b);
		addedge(b,a);
	}
	dfs(1);
	scanf("%d",&m);
	ch=getchar();
	m+=n-1;
	while	(m--){
		scanf("%c%d",&ch,&a);
		if	(ch=='A'){
			scanf("%d\n",&b);
			if	(fa[a]==b)	swap(a,b);
			add(f1[b],-1);
			add(f2[b],1);
		}
		else{
			printf("%d\n",cnt(f1[a])-1);
			ch=getchar();
		}
	}
	return	0;
}

  

转载于:https://www.cnblogs.com/JS-Shining/archive/2013/02/21/2921387.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值