bzoj 1103: [POI2007]大都市meg(树链剖分)

1103: [POI2007]大都市meg

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 2111   Solved: 1104
[ Submit][ Status][ Discuss]

Description

  在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了。
不过,她经常回忆起以前在乡间漫步的情景。昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双
向的土路。从每个村庄都恰好有一条路径到达村庄1(即比特堡)。并且,对于每个村庄,它到比特堡的路径恰好
只经过编号比它的编号小的村庄。另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇。在这个未开
化的地方,从来没有过高架桥和地下铁道。随着时间的推移,越来越多的土路被改造成了公路。至今,Blue Mary
还清晰地记得最后一条土路被改造为公路的情景。现在,这里已经没有土路了——所有的路都成为了公路,而昔日
的村庄已经变成了一个大都市。 Blue Mary想起了在改造期间她送信的经历。她从比特堡出发,需要去某个村庄,
并且在两次送信经历的间隔期间,有某些土路被改造成了公路.现在Blue Mary需要你的帮助:计算出每次送信她需
要走过的土路数目。(对于公路,她可以骑摩托车;而对于土路,她就只好推车了。)

Input

  第一行是一个数n(1 < = n < = 2 50000).以下n-1行,每行两个整数a,b(1 < =  a以下一行包含一个整数m
(1 < = m < = 2 50000),表示Blue Mary曾经在改造期间送过m次信。以下n+m-1行,每行有两种格式的若干信息
,表示按时间先后发生过的n+m-1次事件:若这行为 A a b(a若这行为 W a, 则表示Blue Mary曾经从比特堡送信到
村庄a。

Output

  有m行,每行包含一个整数,表示对应的某次送信时经过的土路数目。

Sample Input

5
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3

Sample Output

2
1
0
1

HINT

Source

[ Submit][ Status][ Discuss]

题解:树链剖分大裸题。

貌似可以用树状数组。。。

#include
#include
#include
#include
#include
#define N 250003
using namespace std;
int n,m;
int tr[N*4],fa[N],size[N],son[N],deep[N],belong[N];
int point[N],next[N*2],v[N*2],tot,pos[N],sz;
void add(int x,int y)
{
	tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;
	tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
void dfs(int x,int f)
{
	deep[x]=deep[f]+1; fa[x]=f; size[x]=1;
	for (int i=point[x];i;i=next[i])
	 if (v[i]!=f){
	 	dfs(v[i],x);
	 	size[x]+=size[v[i]];
	 	if (size[v[i]]>size[son[x]])  son[x]=v[i];
	 }
}
void dfs1(int x,int chain)
{
	belong[x]=chain; pos[x]=++sz; 
	if (!son[x]) return;
	dfs1(son[x],chain);
	for (int i=point[x];i;i=next[i])
	 if (v[i]!=fa[x]&&v[i]!=son[x])
	  dfs1(v[i],v[i]);
}
void update(int now)
{
	tr[now]=tr[now<<1]+tr[now<<1|1];
}
void build(int now,int l,int r)
{
	if (l==r){
		tr[now]=1;
		return;
	}
	int mid=(l+r)/2;
	build(now<<1,l,mid);
	build(now<<1|1,mid+1,r);
	update(now);
}
void change(int now,int l,int r,int x)
{
	if (l==r) {
		tr[now]=0;
		return;
	}
	int mid=(l+r)/2;
	if (x<=mid) change(now<<1,l,mid,x);
	else change(now<<1|1,mid+1,r,x);
	update(now);
}
int qjsum(int now,int l,int r,int ll,int rr)
{
	if (ll<=l&&r<=rr) return tr[now];
	int mid=(l+r)/2;
	int ans=0;
	if (ll<=mid) ans+=qjsum(now<<1,l,mid,ll,rr);
	if (rr>mid) ans+=qjsum(now<<1|1,mid+1,r,ll,rr);
	return ans;
}
int solve(int x,int y)
{
	int ans=0;
	while (belong[x]!=belong[y])
	{
		if (deep[belong[x]]deep[y]) swap(x,y);
	if (pos[x]==pos[y]) return ans;
	ans+=qjsum(1,1,n,pos[x]+1,pos[y]);
	return ans;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("my.out","w",stdout);
	scanf("%d",&n);
	for (int i=1;iy) swap(x,y); 
	 	add(x,y);
	 }
	dfs(1,0); dfs1(1,1);
	build(1,1,n);
	scanf("%d",&m);
	m+=n-1;
	for (int i=1;i<=m;i++)
	{
		char s[10]; scanf("%s",s);
		if (s[0]=='A')
		{
		  int x,y; scanf("%d%d",&x,&y);
		  if (x


你可能感兴趣的:(树链剖分)