• 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
    ",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 }
  • 相关阅读:
    [转] When to use what language and why
    C++常用的函数,好的博客文章整理,集锦
    生活2013
    转-什么样的公司才是好公司?好公司的六大特征
    Linux上去掉ps grep自身查询
    Centos 上搭建FTP服务
    IOS上VOIP PUSH Notification功能
    Linux下常用命令集合
    NodeJS React 开发环境搭建
    MongoDB 命令行导入导出JSON文件
  • 原文地址:https://www.cnblogs.com/lcxer/p/9441481.html
Copyright © 2020-2023  润新知