bzoj 1103 : [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

 

 
水题
 
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1;
const int M = 5e5+10;
int sum[M<<2],lazy[M<<2],son[M],siz[M],head[M],top[M],fa[M],dep[M],tid[M<<2],rk[M<<2];
int u[M],v[M],cnt1,cnt,wt[M],n,m;
struct node{
    int to,next,w;
}e[M];

void add(int u,int v){
    e[++cnt1].to=v;e[cnt1].next=head[u];head[u]=cnt1;
    e[++cnt1].to=u;e[cnt1].next=head[v];head[v]=cnt1;
}
void dfs1(int u,int faz,int deep){
    dep[u] = deep;
    siz[u] = 1;
    fa[u] = faz;
    for(int i = head[u];i ;i=e[i].next){
        int v = e[i].to;
        if(v != fa[u]){
            wt[v] = e[i].w;
            dfs1(v,u,deep+1);
            siz[u] += siz[v];
            if(son[u]==-1||siz[v]>siz[son[u]])
                son[u] = v;
        }
    }
}

void dfs2(int u,int t){
    top[u] = t;
    tid[u] = cnt;
    //cout<<1<<endl;
    cnt++;
    if(son[u] == -1) return ;
    dfs2(son[u],t);
    for(int i = head[u];i;i=e[i].next){
        int v = e[i].to;
        if(v != son[u]&&v != fa[u])
            dfs2(v,v);
    }
}

void pushup(int rt){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}

void pushdown(int rt){
    if(lazy[rt]){
        sum[rt<<1] = sum[rt<<1|1] = lazy[rt] = 0;
        lazy[rt<<1] = lazy[rt<<1|1] = 1;
    }
}

void build(int l,int r,int rt){
    if(l == r){
        sum[rt] = 1;
        return ;
    }
    mid;
    build(lson); build(rson);
    pushup(rt);
}

void update(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        sum[rt] = 0;
        lazy[rt] = 1;
        return ;
    }
    pushdown(rt);
    mid;
    if(L <= m) update(L,R,lson);
    if(R > m) update(L,R,rson);
    pushup(rt);
}

int query(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return sum[rt];
    }
    pushdown(rt);
    mid;
    int ret = 0;
    if(L <= m) ret += query(L,R,lson);
    if(R > m) ret += query(L,R,rson);
    return ret;
}

void update(int x,int y){
    int fx = top[x],fy = top[y];
    while(fx != fy){
        if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
        if(fx == 1) update(tid[fx]+1,tid[x],1,n,1);
        else update(tid[fx],tid[x],1,n,1);
        x = fa[fx]; fx = top[x];
    }
    if(x == y) return ;
    if(dep[x] > dep[y]) swap(x,y);
    update(tid[x]+1,tid[y],1,n,1);
    return ;
}

int solve(int x,int y){
    int ans = 0;
    int fx = top[x],fy = top[y];
    while(fx != fy){
        if(dep[fx] < dep[fy]) swap(x,y),swap(fx,fy);
        if(fx == 1) ans += query(tid[fx]+1,tid[x],1,n,1);
        else ans += query(tid[fx],tid[x],1,n,1);
        x = fa[fx]; fx = top[x];
    }
    if(x == y) return ans;
    if(dep[x] > dep[y]) swap(x,y);
    ans += query(tid[x]+1,tid[y],1,n,1);
    return ans;
}

int main()
{
    int u,v,l,r,q,x;
    char op[100];
    scanf("%d",&n);
    memset(son,-1,sizeof(son));
    for(int i = 2;i <= n;i ++){
        scanf("%d%d",&u,&v);
        add(u,v);
    }
    dfs1(1,0,1); dfs2(1,0);
    build(1,n,1);
    scanf("%d",&q);
    q += n-1;
    while(q--){
        scanf("%s",op);
        if(op[0] == 'W'){
            scanf("%d",&x);
            printf("%d\n",solve(x,1));
        }
        else {
            scanf("%d%d",&l,&r);
            update(l,r);
        }
    }
    return 0;
}

 

posted @ 2018-11-05 19:19  冥想选手  阅读(171)  评论(0编辑  收藏  举报