BZOJ1103 [POI2007]大都市meg dfs序 线段树

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1103


题意概括

  一棵树上,一开始所有的边权值为1,我们要支持两种操作:

  1. 修改某一条边的权值为0

  2. 询问根节点到某一节点的路径权值和


 

题解

  前置技能 - dfs序相关

  然后差不多你就会了。

  dfs序+线段树搞定了。


 

代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=250000+5;
struct Gragh{
    int cnt,x[N],y[N],nxt[N],fst[N];
    void set(){
        cnt=0;
        memset(fst,0,sizeof fst);
    }
    void add(int a,int b){
        x[++cnt]=a,y[cnt]=b;
        nxt[cnt]=fst[a],fst[a]=cnt;
    }
}g;
int n,m,fa[N],in[N],out[N],dis[N],time;
char ch[3];
struct SegTree{
    int v,add;
}t[N*4];
void dfs(int rt){
    in[rt]=++time;
    for (int i=g.fst[rt];i;i=g.nxt[i])
        dis[g.y[i]]=dis[rt]+1,dfs(g.y[i]);
    out[rt]=time;
}
void build(int rt,int le,int ri){
    t[rt].add=t[rt].v=0;
    if (le==ri)
        return;
    int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    build(ls,le,mid);
    build(rs,mid+1,ri);
}
void pushdown(int rt){
    if (!t[rt].add)
        return;
    int ls=rt<<1,rs=ls|1,&v=t[rt].add;
    t[ls].add+=v,t[ls].v+=v;
    t[rs].add+=v,t[rs].v+=v;
    v=0;
}
void update(int rt,int le,int ri,int xle,int xri){
    if (ri<xle||le>xri)
        return;
    if (xle<=le&&ri<=xri){
        t[rt].add++,t[rt].v++;
        return;
    }
    pushdown(rt);
    int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    update(ls,le,mid,xle,xri);
    update(rs,mid+1,ri,xle,xri);
}
int query(int rt,int le,int ri,int x){
    if (le==ri)
        return t[rt].v;
    pushdown(rt);
    int mid=(le+ri)>>1,ls=rt<<1,rs=ls|1;
    if (x<=mid)
        return query(ls,le,mid,x);
    else
        return query(rs,mid+1,ri,x);
}
int main(){
    g.set();
    scanf("%d",&n);
    for (int i=1,a,b;i<n;i++){
        scanf("%d%d",&a,&b);
        if (a>b)
            swap(a,b);
        fa[b]=a,g.add(a,b);
    }
    time=dis[1]=0;
    dfs(1);
    build(1,1,n);
    scanf("%d",&m);
    m+=n-1;
    while (m--){
        int x,a,b;
        scanf("%s",ch);
        if (ch[0]=='W'){
            scanf("%d",&x);
            printf("%d\n",dis[x]-query(1,1,n,in[x]));
        }
        else {
            scanf("%d%d",&a,&b);
            if (a>b)
                swap(a,b);
            update(1,1,n,in[b],out[b]);
        }
    }
    return 0;
}

 

posted @ 2017-08-17 16:59  zzd233  阅读(236)  评论(0编辑  收藏  举报