zoukankan      html  css  js  c++  java
  • BZOJ1103: [POI2007]大都市meg

    BZOJ1103: [POI2007]大都市meg

    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

    题解Here!

    树链剖分水题。。。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA(x) b[x].data
    #define SIGN(x) b[x].c
    #define LSIDE(x) b[x].l
    #define RSIDE(x) b[x].r
    #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
    #define MAXN 250010
    using namespace std;
    int n,m,c=1,d=1;
    int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
    struct Graph{
        int next,to;
    }a[MAXN<<1];
    struct Segment_Tree{
        int data,c,l,r;
    }b[MAXN<<2];
    inline int read(){
        int date=0,w=1;char c=0,last=0;
        while(c<'0'||c>'9'){last=c;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        if(last=='-')w=-1;
        return date*w;
    }
    inline void pushup(int rt){
        DATA(rt)=DATA(LSON)+DATA(RSON);
    }
    inline void pushdown(int rt){
        if(SIGN(rt)==-1||LSIDE(rt)==RSIDE(rt))return;
        SIGN(LSON)=SIGN(rt);
        DATA(LSON)=SIGN(rt)*WIDTH(LSON);
        SIGN(RSON)=SIGN(rt);
        DATA(RSON)=SIGN(rt)*WIDTH(RSON);
        SIGN(rt)=-1;
    }
    void buildtree(int l,int r,int rt){
        int mid;
        LSIDE(rt)=l;
        RSIDE(rt)=r;
        SIGN(rt)=-1;
        if(l==r){
            DATA(rt)=1;
            if(l==1)DATA(rt)=0;
            return;
        }
        mid=l+r>>1;
        buildtree(l,mid,LSON);
        buildtree(mid+1,r,RSON);
        pushup(rt);
    }
    void update(int l,int r,int c,int rt){
        int mid;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
            SIGN(rt)=c;
            DATA(rt)=c*WIDTH(rt);
            return;
        }
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)update(l,r,c,LSON);
        if(mid<r)update(l,r,c,RSON);
        pushup(rt);
    }
    int query(int l,int r,int rt){
        int mid,ans=0;
        if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return DATA(rt);
        pushdown(rt);
        mid=LSIDE(rt)+RSIDE(rt)>>1;
        if(l<=mid)ans+=query(l,r,LSON);
        if(mid<r)ans+=query(l,r,RSON);
        return ans;
    }
    inline void add(int x,int y){
        a[c].to=y;a[c].next=head[x];head[x]=c++;
        a[c].to=x;a[c].next=head[y];head[y]=c++;
    }
    void dfs1(int rt){
        son[rt]=0;size[rt]=1;
        for(int i=head[rt];i;i=a[i].next){
            int will=a[i].to;
            if(!deep[will]){
                deep[will]=deep[rt]+1;
                fa[will]=rt;
                dfs1(will);
                size[rt]+=size[will];
                if(size[son[rt]]<size[will])son[rt]=will;
            }
        }
    }
    void dfs2(int rt,int f){
        id[rt]=d++;top[rt]=f;
        if(son[rt])dfs2(son[rt],f);
        for(int i=head[rt];i;i=a[i].next){
            int will=a[i].to;
            if(will!=fa[rt]&&will!=son[rt])
            dfs2(will,will);
        }
    }
    void work_change(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            update(id[top[x]],id[x],0,1);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        update(id[x]+1,id[y],0,1);
        return;
    }
    void work_sum(int x,int y){
        int s=0;
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            s+=query(id[top[x]],id[x],1);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        s+=query(id[x]+1,id[y],1);
        printf("%d
    ",s);
        return;
    }
    void work(){
        char ch[2];
        int x,y;
        m=read()+n-1;
        while(m--){
            scanf("%s",ch);x=read();
            if(ch[0]=='A'){
                y=read();
                work_change(x,y);
            }
            else work_sum(1,x);
        }
    }
    void init(){
        int x,y;
        n=read();
        for(int i=1;i<n;i++){
            x=read();y=read();
            add(x,y);
        }
        deep[1]=1;
        dfs1(1);
        dfs2(1,1);
        buildtree(1,n,1);
    }
    int main(){
        init();
        work();
        return 0;
    }
    
  • 相关阅读:
    android之Activity回传数据
    Android之Activity启动模式
    桥接模式
    Android之Activity跳转
    Android多线程文件下载
    代理模式
    适配器模式
    vs2010 入门程序
    文件动态打开获取数据
    项目测试一 批量读取数据到数组
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9375062.html
Copyright © 2011-2022 走看看