BZOJ 1103 DFS序+线段树

思路:
先搞出来DFS序
进入这个点 +1
出这个点 -1

线段树维护前缀和 (因为还要修改) 搞定
修改的时候只修改底下节点就OK了 (边权–>点权 不多说)

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 555000
char ch[55];
int n,m,nn,sum,v[N],next[N],first[N],tree[N*4],tot,cnt,in[N],out[N],xx,yy;
void add(int x,int y){
    v[tot]=y,next[tot]=first[x],first[x]=tot++;
}
void insert(int l,int r,int pos,int x,int wei){
    if(l==r){tree[pos]+=wei;return;}
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<x)insert(mid+1,r,rson,x,wei);
    else insert(l,mid,lson,x,wei);
    tree[pos]=tree[lson]+tree[rson];
}
void dfs(int x,int fa){
    in[x]=++cnt,insert(1,nn,1,cnt,1);
    for(int i=first[x];~i;i=next[i])
        if(v[i]!=fa)dfs(v[i],x);
    out[x]=++cnt,insert(1,nn,1,cnt,-1);
}
int query(int l,int r,int pos){
    if(r<=yy)return tree[pos];
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid>=yy)return query(l,mid,lson);
    else return query(l,mid,lson)+query(mid+1,r,rson);
}
int main(){
    memset(first,-1,sizeof(first));
    scanf("%d",&n),nn=2*n;
    for(int i=1;i<n;i++){
        scanf("%d%d",&xx,&yy);
        add(xx,yy),add(yy,xx);
    }
    dfs(1,-1);
    scanf("%d",&m);
    for(int i=1;i<n+m;i++){
        scanf("%s%d",ch,&xx);
        if(ch[0]=='W')yy=in[xx],printf("%d\n",query(1,nn,1)-1);
        else{
            scanf("%d",&yy);
            if(in[xx]>in[yy])swap(xx,yy);
            insert(1,nn,1,in[yy],-1),insert(1,nn,1,out[yy],1);
        }
    }
}

这里写图片描述

posted @ 2016-10-15 13:32  SiriusRen  阅读(154)  评论(0编辑  收藏  举报