bzoj1103[POI2007]大都市meg

1103: [POI2007]大都市meg 
Time Limit: 10 Sec Memory Limit: 162 MB 
Submit: 3232 Solved: 1692 
[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


HINT

Source

[Submit][Status][Discuss] 
 
HOME Back 
我很想发图,可惜不知道怎么发 
那就直接讲吧 
可以直接去bzoj传送门看题面 
这题暴力是显然很好想的 
显然是可以对于每个询问去进行dfs 
当然是很慢的,因为浪费了巨大的时间 
去每个点都只有一条路径,而dfs会访问所有的可达点 
所以处理出路径可以节省巨大的时间 
显然是dfs序,但是我不会保存,就写了树剖,慢的心累 
这个就不用我讲了吧,树剖用在这里正确性是很显然的 
双向边建边数组开2倍

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 int now,id[250001],top[250001],v,m,n,ca,cnt,h[250001],nxt[500001],pre[500001],size[250001],dep[250001],ans,f[250001];
  5 struct oo{int a,b,v;}s[1000001];
  6 void add(int x,int y)
  7 {
  8     pre[++cnt]=y;
  9     nxt[cnt]=h[x];
 10     h[x]=cnt;
 11 }
 12 void dfs(int x)
 13 {
 14     size[x]=1;
 15     for(int i=h[x];i;i=nxt[i])
 16         {
 17             int w=pre[i];
 18             if(f[x]==w)continue;
 19             f[w]=x;
 20             dep[w]=dep[x]+1;
 21             dfs(w);
 22             size[x]+=size[w];
 23         }
 24 }
 25 void dfs1(int x,int fa)
 26 {
 27     int k=0;
 28     id[x]=++now;top[x]=fa;
 29     for(int i=h[x];i;i=nxt[i])
 30         if(dep[pre[i]]>dep[x]&&size[pre[i]]>size[k])k=pre[i];
 31     if(!k)return ;
 32     dfs1(k,fa);
 33     for(int i=h[x];i;i=nxt[i])
 34         if(dep[pre[i]]>dep[x]&&pre[i]!=k)dfs1(pre[i],pre[i]);
 35 }
 36 void build(int x,int l,int r)
 37 {
 38     s[x].a=l,s[x].b=r;
 39     if(l==r){s[x].v=1;return ;}
 40     build(x<<1,l,(l+r)>>1);
 41     build(x<<1|1,((l+r)>>1)+1,r);
 42     s[x].v=s[x<<1].v+s[x<<1|1].v;
 43 }
 44 void change(int x,int y)
 45 {
 46     s[x].v--;
 47     if(s[x].a==s[x].b)return ;
 48     int mid=(s[x].a+s[x].b)>>1;
 49     if(y<=mid)change(x<<1,y);
 50     else change(x<<1|1,y);
 51 }
 52 void sum(int x,int l,int r)
 53 {
 54     if(l<=s[x].a&&r>=s[x].b)
 55         ca+=s[x].v;
 56     else 
 57         {
 58             int mid=(s[x].a+s[x].b)>>1;
 59             if(l<=mid)sum(x<<1,l,r);
 60             if(r>mid)sum(x<<1|1,l,r);
 61         }
 62 }
 63 void qsum(int x,int y)
 64 {
 65     ans=0;ca=0;
 66     while(top[x]!=top[y])
 67         {
 68             if(dep[top[x]]<dep[top[y]])swap(x,y);
 69             sum(1,id[top[x]],id[x]);
 70             ans+=ca;ca=0;
 71             x=f[top[x]];
 72         }
 73     if(id[x]>id[y])swap(x,y);
 74     sum(1,id[x]+1,id[y]);
 75     ans+=ca;
 76     printf("%d\n",ans);
 77 }
 78 int main()
 79 {
 80     scanf("%d",&n);
 81     for(int i=1,x,y;i<n;i++)
 82         {
 83             scanf("%d%d",&x,&y);
 84             add(x,y),add(y,x);
 85         }
 86     dfs(1);dfs1(1,1);build(1,1,n);
 87     scanf("%d",&m);
 88     char p[6];
 89     for(int i=1,x,y;i<=n+m-1;i++)
 90         {
 91             scanf("%s",p+1);
 92             if(p[1]=='W')
 93                 {
 94                     scanf("%d",&x);
 95                     qsum(1,x);
 96                 }
 97             else 
 98                 {
 99                     scanf("%d%d",&x,&y);
100                     change(1,id[y]);
101                 }
102         }
103 }

 

posted @ 2018-08-08 10:58  蒟蒻--lichenxi  阅读(123)  评论(0编辑  收藏  举报