hdu3974(dfs序建线段树)

来源:互联网 发布:win8.1优化 编辑:程序博客网 时间:2024/06/06 08:26

链接:点击打开链接

题意:给出一个有向树,初始所有节点为-1.有两种操作,一种为(T,x,y),表示将x节点的所有子树中的节点变为y,另一种为(C,x),为求x节点的值

代码:

#include <queue>#include <math.h>#include <vector>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int siz=50005;int tree[siz<<3];void build(int l,int r,int rt){    tree[rt]=-1;    if(l==r)    return;    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);}void pushdown(int rt){    if(tree[rt]!=-1){        tree[rt<<1]=tree[rt];        tree[rt<<1|1]=tree[rt];        tree[rt]=-1;    }}void Change(int L,int R,int p,int l,int r,int rt){    if(L<=l&&r<=R){        tree[rt]=p;        return;    }    pushdown(rt);    int m=(l+r)>>1;    if(L<=m)    Change(L,R,p,l,m,rt<<1);    if(R>m)    Change(L,R,p,m+1,r,rt<<1|1);}int query(int p,int l,int r,int rt){    if(l==r)    return tree[rt];    pushdown(rt);    int m=(l+r)>>1;    if(p<=m)    query(p,l,m,rt<<1);    else    query(p,m+1,r,rt<<1|1);}vector<int> G[siz];int ll[siz],rr[siz],vis[siz];void dfs(int s,int &id){    int i,tmp;    ll[s]=id++;    for(i=0;i<G[s].size();i++){        tmp=G[s][i];        dfs(tmp,id);    }    rr[s]=id++;}int main(){    char ch;    int t,n,m,u,v,i,id,cas=1;    scanf("%d",&t);    while(t--){                                 //用dfs序建树,直接就转换为        scanf("%d",&n);                         //线段树区间更新,单点查询        build(1,2*n,1);        for(i=1;i<=n;i++)        vis[i]=0,G[i].clear();        for(i=1;i<n;i++){            scanf("%d%d",&u,&v);            G[v].push_back(u);            vis[u]=1;        }        memset(ll,-1,sizeof(ll));        memset(rr,-1,sizeof(rr));        id=1;        for(i=1;i<=n;i++)                       //有向树找根节点        if(vis[i]==0)        dfs(i,id);        scanf("%d",&m);        printf("Case #%d:\n",cas++);        while(m--){            cin>>ch;            if(ch=='C'){                scanf("%d",&u);                                 printf("%d\n",query(ll[u],1,2*n,1));            }            else{                scanf("%d%d",&u,&v);            //每次更新只要在第一次出现改点的dfs序                Change(ll[u],rr[u],v,1,2*n,1);  //和最后一次出现改点的dfs序之间区间更新即可            }        }    }    return 0;}