1. 程式人生 > >線段樹(dfs序建樹加區間更新和單點查詢)

線段樹(dfs序建樹加區間更新和單點查詢)

記錄一下這道折磨了我一天的題,。。。。

具體思路: 具體關係可通過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;
}