CF 258E Little Elephant and Tree(DFS+线段树)

转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove

题目:给出一棵树,每次操作给出两个结点a,b,表示将以a,b为根的两棵子树的所有结点,都加入一个相同的数i,i表示操作序号。
然后查询所有的点,和自己至少有1个相同数字的结点有多少个
http://codeforces.com/problemset/problem/258/E 
关于这种对于整棵子树操作,烂大街了吧。。。(= =其实只是在CF上做过两题吧
首先DFS一下,给每个结点一个编号,那么对于某一个结点,他的子树的结点的编号便是一个连续的区间[s[i],e[i]]
这样的话,对于某一个操作,就相当于对于整个线段插入了同一个数
然后还是按树的DFS序去更新线段树,查询有多少个点被覆盖就行了
#include<iostream>  
#include<cstdio>  
#include<map>  
#include<cstring>  
#include<cmath>  
#include<vector>  
#include<algorithm>  
#include<set>  
#include<string>  
#include<queue>  
#define inf 1600005  
#define M 40  
#define N 100005
#define maxn 300005  
#define eps 1e-12
#define zero(a) fabs(a)<eps  
#define Min(a,b) ((a)<(b)?(a):(b))  
#define Max(a,b) ((a)>(b)?(a):(b))  
#define pb(a) push_back(a)  
#define mp(a,b) make_pair(a,b)  
#define mem(a,b) memset(a,b,sizeof(a))  
#define LL long long  
#define MOD 1000000007
#define lson step<<1
#define rson step<<1|1
#define sqr(a) ((a)*(a))  
#define Key_value ch[ch[root][1]][0]  
#define test puts("OK");  
#define pi acos(-1.0)
#define lowbit(x) ((-(x))&(x))
#pragma comment(linker, "/STACK:1024000000,1024000000")  
using namespace std;
struct Seg_tree{
    int left,right;
    int cnt,lazy;
    int length(){
        return right-left+1;
    }
}L[N*4];
int s[N],e[N],tot;
int n,m;
int ans[N];
vector<int>edge[N],que[N];
void Bulid(int step,int l,int r){
    L[step].left=l;
    L[step].right=r;
    L[step].cnt=L[step].lazy=0;
    if(l==r)
        return ;
    int m=(l+r)>>1;
    Bulid(lson,l,m);
    Bulid(rson,m+1,r);
}
void Push_Up(int step){
    if(L[step].lazy) L[step].cnt=L[step].length();
    else {
        if(L[step].left==L[step].right) L[step].cnt=0;
        else L[step].cnt=L[lson].cnt+L[rson].cnt;
    }
}
void Update(int step,int l,int r,int val){
    if(L[step].left==l&&r==L[step].right){
        L[step].lazy+=val;
        Push_Up(step);
        return ;
    }
    int m=(L[step].left+L[step].right)>>1;
    if(r<=m) Update(lson,l,r,val);
    else if(l>m) Update(rson,l,r,val);
    else{
        Update(lson,l,m,val);
        Update(rson,m+1,r,val);
    }
    Push_Up(step);
}
void dfs(int u,int pre){
    s[u]=++tot;
    for(int i=0;i<edge[u].size();i++){
        int v=edge[u][i];
        if(v==pre) continue;
        dfs(v,u);
    }
    e[u]=tot;
}
void Init(){
    for(int i=1;i<=n;i++){
        edge[i].clear();
        que[i].clear();
    }
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        edge[u].pb(v);edge[v].pb(u);
    }
    for(int i=0;i<m;i++){
        int a,b;
        scanf("%d%d",&a,&b);
        que[a].pb(b);que[a].pb(a);
        que[b].pb(a);que[b].pb(b);
    }
    tot=0;
    dfs(1,-1);
    Bulid(1,1,n);
}
void Slove(int u,int pre){
    for(int i=0;i<que[u].size();i++){
        int v=que[u][i];
        Update(1,s[v],e[v],1);
    }
    ans[u]=L[1].cnt;
    if(ans[u])
        ans[u]--;
    for(int i=0;i<edge[u].size();i++){
        int v=edge[u][i];
        if(v==pre) 
            continue;
        Slove(v,u);
    }
    for(int i=0;i<que[u].size();i++){
        int v=que[u][i];
        Update(1,s[v],e[v],-1);
    }
}
void Output(){
    for(int i=1;i<n;i++)
        printf("%d ",ans[i]);
    printf("%d\n",ans[n]);
}
int main(){
    //freopen("input.txt","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF){
        Init();
        Slove(1,-1);
        Output();
    }
    return 0;
}


你可能感兴趣的:(CF 258E Little Elephant and Tree(DFS+线段树))