线段树(dfs序建树加区间更新和单点查询)

题目链接:https://cn.vjudge.net/contest/66989#problem/J

记录一下这道折磨了我一天的题,。。。。

具体思路: 具体关系可通过dfs序建树,但是注意,在更新以及查询时的数和你dfs序建成的数是不一样的。因为你dfs序建成的树每个左右区间以及端点会发生不符合建树的条件。但是具体区间的更新还是可以通过新的树进行更新的,但是下属关系还是符合线段树的规则的,区间越大,也就是管理的人越多,也就是端点越往上。

AC代码;

#include<iostream>
#include<string>
#include<cstring>
#include<iomanip>
#include<map>
#include<cmath>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<stdio.h>
using namespace std;
# define inf 0x3f3f3f3f
# define maxn 500000+100
# define ll long long
# define lson l,m,rt<<1
# define rson m+1,r,rt<<1|1
vector<int>wakaka[maxn];
int vis[maxn];
int st[maxn];
int ed[maxn];
bool cover[maxn];
int ans;
int num;
int a[maxn];
void init()
{
    memset(cover,0,sizeof(a));
    memset(vis,0,sizeof(vis));
    memset(st,0,sizeof(st));
    memset(ed,0,sizeof(ed));
    num=0;
}
void cal(int rt,int l,int r)
{
    if(a[rt]==-1||l==r)return ;//必须先判断a[rt]是不是-1,如果是-1.则不能往下更新。
    a[rt<<1]=a[rt<<1|1]=a[rt];
    a[rt]=-1;
}
void dfs(int u)
{
    st[u]=++num;
    int len=wakaka[u].size();
    for(int i=0; i<len; i++)
    {
        dfs(wakaka[u][i]);
    }
    ed[u]=num;
}
int query(int p,int l,int r,int rt)
{
    if(l==r)//单点查询
    {
        return a[rt];
    }
    cal(rt,l,r);
    int m=(l+r)>>1;
    if(p<=m)query(p,lson);
    else if(p>m)query(p,rson);
}
void update(int col,int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        a[rt]=col;
        return ;
    }
    cal(rt,l,r);
    int m=(l+r)>>1;
    if(L<=m)update(col,L,R,lson);
    if(R>m)update(col,L,R,rson);
}
int main()
{
    int T;
    scanf("%d",&T);
    int t=0;
    while(T--)
    {
        int n,u,v;
        scanf("%d",&n);
        init();
        for(int i=1; i<=n; i++){
        wakaka[i].clear();
        }
        memset(a,-1,sizeof(a));
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&u,&v);
            wakaka[v].push_back(u);
            vis[u]=1;
        }
        for(int i=1; i<=n; i++)
        {
            if(!vis[i])
            {
                dfs(i);
                break;
            }
        }
        int m1;
        scanf("%d",&m1);
        char str[10];
        int t1,t2;
        printf("Case #%d:\n",++t);
        while(m1--)
        {
            scanf("%s",str);
            if(str[0]=='C')
            {
                scanf("%d",&t1);
                printf("%d\n",query(st[t1],1,n,1));//直接查询单点.
            }
            else if(str[0]=='T')
            {
                scanf("%d%d",&t1,&t2);
                update(t2,st[t1],ed[t1],1,n,1);//更新区间。
            }
        }
    }
    return 0;
}



 

posted @ 2018-10-21 16:56  Let_Life_Stop  阅读(378)  评论(0编辑  收藏  举报