1103. [POI2007]MEG-Megalopolis【树链剖分】

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

1103. [POI2007]MEG-Megalopolis【树链剖分】

就是一道裸的树链剖分啊……
过程中唯一的一点小麻烦(好像也算不上麻烦)
就是把边看成点做0v0
所以Change的时候最后当两个点在同一条重链上就修改
Update(1,1,n,T_NUM[Son[x]],T_NUM[y],1);

 #include<iostream>
#include<cstdio>
#define MAX (250000+10)
using namespace std; int Depth[MAX],Son[MAX],Father[MAX],Sum[MAX];
int head[MAX],num_edge,sum;
int Top[MAX],T_NUM[MAX],n;
struct node
{
int to,next;
}edge[MAX*];
struct node1
{
int add,down;
}Segt[MAX*]; void Add(int u,int v)
{
edge[++num_edge].to=v;
edge[num_edge].next=head[u];
head[u]=num_edge;
} void Dfs1(int x)
{
Depth[x]=Depth[Father[x]]+;
Sum[x]=;
for (int i=head[x];i!=;i=edge[i].next)
if (edge[i].to!=Father[x])
{
Father[edge[i].to]=x;
Dfs1(edge[i].to);
Sum[x]+=Sum[edge[i].to];
if (Son[x]== || Sum[Son[x]]<Sum[edge[i].to])
Son[x]=edge[i].to;
}
} void Dfs2(int x,int pre)
{
T_NUM[x]=++sum;
Top[x]=pre;
if (Son[x]!=)
Dfs2(Son[x],pre);
for (int i=head[x];i!=;i=edge[i].next)
{
if (edge[i].to!=Father[x] && edge[i].to!=Son[x])
Dfs2(edge[i].to,edge[i].to);
}
} void Pushdown(int node,int l,int r)
{
if (Segt[node].down!=)
{
Segt[node*].down=Segt[node].down;
Segt[node*+].down=Segt[node].down;
int mid=(l+r)/;
Segt[node*].add=Segt[node].down*(mid-l+);
Segt[node*].add=Segt[node].down*(r-mid);
Segt[node].down=;
}
} void Update(int node,int l,int r,int l1,int r1,int k)
{
if (r<l1 || l>r1)
return;
if (l1<=l && r<=r1)
{
Segt[node].add=(r-l+)*k;
Segt[node].down=k;
return;
}
Pushdown(node,l,r);
int mid=(l+r)/;
Update(node*,l,mid,l1,r1,k);
Update(node*+,mid+,r,l1,r1,k);
Segt[node].add=Segt[node*].add+Segt[node*+].add;
} int Query(int node,int l,int r,int l1,int r1)
{
if (r<l1 || l>r1)
return ;
if (l1<=l && r<=r1)
return Segt[node].add;
Pushdown(node,l,r);
int mid=(l+r)/;
return Query(node*,l,mid,l1,r1)+
Query(node*+,mid+,r,l1,r1); } void Change(int x,int y)
{
int fx=Top[x],fy=Top[y];
while (fx!=fy)
{
if (Depth[fx]<Depth[fy])
swap(fx,fy),swap(x,y);
Update(,,n,T_NUM[fx],T_NUM[x],);
x=Father[fx];fx=Top[x];
}
if (Depth[x]>Depth[y])
swap(x,y);
Update(,,n,T_NUM[Son[x]],T_NUM[y],);
} int Ask(int x)//0为土路1为公路
{
int ans=,fx=Top[x],sum=Depth[x]-;
while (x!=)
{
ans+=Query(,,n,T_NUM[fx],T_NUM[x]);
x=Father[fx],fx=Top[x];
}
return sum-ans;
} int main()
{
int u,v,m,x,y;
char p;
scanf("%d",&n);
for (int i=;i<=n-;++i)
{
scanf("%d%d",&u,&v);
Add(u,v);
Add(v,u);
}
Dfs1();
Dfs2(,);
scanf("%d",&m);
for (int i=;i<=n+m-;++i)
{
scanf("%c",&p);
while (p!='W' && p!='A')
scanf("%c",&p);
if (p=='W')
scanf("%d",&x),printf("%d\n",Ask(x));
else
scanf("%d%d",&x,&y),Change(x,y);
}
}
上一篇:C#基础知识回顾--BackgroundWorker介绍


下一篇:springcloud-eureka简单实现