您的位置:首页 > 其它

BZOJ1103 [POI2007]大都市meg

2016-10-02 17:08 274 查看

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



正解:树链剖分

解题报告:

  链剖裸题。dfs序+树状数组也可以做。

//It is made by jump~
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 250011;
const int inf = (1<<30);
int n,total,ecnt,ans;
int id[MAXN],ql,qr;
int pre[MAXN],TT;
int top[MAXN],siz[MAXN],zhongerzi[MAXN],father[MAXN],deep[MAXN];
int next[MAXN*2],to[MAXN*2],first[MAXN];
char ch[12];

struct node{
int sum;
}a[MAXN*4];
inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; }
inline int getint()
{
int w=0,q=0;
char c=getchar();
while((c<'0' || c>'9') && c!='-') c=getchar();
if (c=='-')  q=1, c=getchar();
while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
return q ? -w : w;
}

inline void build(int root,int l,int r){
if(l==r){ if(l!=1) a[root].sum=1; else a[root].sum=0; return ; }
int lc=root*2,rc=lc+1;
int mid=(l+r)/2;  build(lc,l,mid); build(rc,mid+1,r);
a[root].sum=a[lc].sum+a[rc].sum;
}

inline void dfs1(int u,int fa){
siz[u]=1;
for(int i=first[u];i;i=next[i]){
int v=to[i]; if(v==fa) continue;
father[v]=u;deep[v]=deep[u]+1;
dfs1(v,u);siz[u]+=siz[v];
if(siz[v]>siz[ zhongerzi[u] ]) zhongerzi[u]=v;
}
}

inline void dfs2(int u,int fa){
id[u]=++total; pre[total]=u;
if(zhongerzi[u]) {  top[zhongerzi[u]]=top[u];dfs2(zhongerzi[u],u); }
for(int i=first[u];i;i=next[i]){
int v=to[i]; if(v==fa || v==zhongerzi[u]) continue;
top[v]=v; dfs2(v,u);
}
}

inline void querysum(int root,int l,int r){
if(ql<=l && r<=qr) { ans+=a[root].sum; return ; }
int mid=(l+r)/2; int lc=root*2,rc=lc+1;
if(ql<=mid) querysum(lc,l,mid);
if(qr>mid) querysum(rc,mid+1,r);
}

inline int findsum(int x){
int f1=top[x]; ans=0;
while(f1!=0){
ql=id[f1]; qr=id[x];   querysum(1,1,n);
x=father[f1]; f1=top[x];
}
return ans;
}

inline void update(int root,int l,int r){
if(l==r) { a[root].sum=0;  return ; }
int mid=(l+r)/2; int lc=root*2,rc=lc+1;
if(TT<=mid) update(lc,l,mid); else update(rc,mid+1,r);
a[root].sum=a[lc].sum+a[rc].sum;
}

inline void work(){
n=getint(); int x,y;
for(int i=1;i<n;i++){
x=getint();y=getint(); if(x>y) swap(x,y);
link(x,y);
}
deep[1]=1;  dfs1(1,0);
top[1]=1;  dfs2(1,0);
build(1,1,n);
int Q=getint(); Q+=n-1;

for(int i=1;i<=Q;i++){
scanf("%s",ch);
if(ch[0]=='W'){
x=getint();
printf("%d\n",findsum(x));
}
else{
x=getint(); y=getint(); if(x<y) swap(x,y); TT=id[x];
update(1,1,n);
}
}
}

int main()
{
work();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: