题意:题意就是给你一颗树,然后如果你给一节点上赋值,那么他下面的所以子节点都会被赋上这个值,现在有两个操作:1 查询某个节点上的值,2.修改某个节点上的值 (注意他下面的值也会改变)
思路:就是,我们在树上跑一边dfs然后给这颗树上的每个节点都重新编号,得到一个high数组和一个low数组,其实high数组表示的是区间左端点,low数组表示的区间右端点
之后就是对区间进行的操作了 ,然后查询就单点查询就好了 ,相通了还是挺简单的上代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define lson l , m ,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 50200;
int sum[maxn<<2] , high[maxn] , low[maxn]; //high 管辖的头结点 low 尾节点
int head[maxn] , cnt , vis[maxn],tot , p[maxn] , n ,lazy[maxn<<2];
struct node
{
int to,next;
}edg[maxn<<1];
void add(int u ,int v)
{
edg[cnt].to=v;
edg[cnt].next = head[u];
head[u] = cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(lazy,0,sizeof(lazy));
memset(sum,0,sizeof(sum));
memset(high,0,sizeof(high));
memset(low,0,sizeof(low));
cnt = 0 ;
tot = 0 ;
for(int i = 1 ; i <= n ;i++)
{
p[i] = i;
}
}
int getf(int v)
{
return p[v] = v ? p[v] : getf(v);
}
void dfs(int v)
{
if(vis[v]) return ;
high[v] = ++tot;
for(int i = head[v] ; i!=-1 ; i = edg[i].next)
{
int p = edg[i].to;
dfs(p);
}
low[v] = tot;
}
void pushdown(int rt)
{
if(lazy[rt] != 0 )
{
lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
sum[rt<<1] = lazy[rt];
sum[rt<<1|1] = lazy[rt];
// printf("sum[rt] = %d sum[rt<<1] = %d lazy = %d\n",sum[rt<<1] , sum[rt<<1|1] , lazy[rt]);
lazy[rt] = 0;
}
}
void build(int l , int r , int rt)
{
sum[rt] = 0;
if(l == r) return ;
int m = (l + r)>>1;
build(lson);
build(rson);
}
void update(int L , int R , int add , int l , int r , int rt)
{
if(l>=L&&R>=r)
{
sum[rt] = add;
lazy[rt] = add;
return ;
}
pushdown(rt);
int m = (r+l)>>1;
if(m>=L)
{
update(L,R,add,lson);
}
if(R>m)
{
update(L,R,add,rson);
}
}
/*int query(int L ,int R ,int l ,int r , int rt)
{
if(l>=L&&R>=r)
{
return sum[rt];
}
pushdown(rt);
int m = (l + r)>>1;
int ret = 0;
if(m>=L)
{
ret = query(L,R,lson);
}
if(R>m)
{
ret = query(L,R,rson);
}
return ret;
}*/
int query(int p, int l,int r ,int rt)
{
if(l == r) return sum[rt];
pushdown(rt);
int m = (l+r)>>1;
if(m>=p) query(p,lson);
else query(p,rson);
}
int main()
{
int t;
int flag = 0 ;
char op[2];
scanf("%d",&t);
while(t--)
{
int a,b;
scanf("%d",&n);
init();
for(int i = 0 ; i < n-1 ; i++)
{
scanf("%d%d",&a,&b);//建边的时候要换一下
add(b,a);
int da = getf(a);
int db = getf(b);//并查集 是为了找到树的根节点在哪里
if(da!=db)
{
p[da] = db;
}
}
int p = getf(1);//根节点
dfs(p);//从根节点开始深搜
int m;
scanf("%d",&m);
printf("Case #%d:\n",++flag);
for(int i = 0 ; i < m ; i++)
{
scanf("%s",op);
if(op[0] == 'C')
{
scanf("%d",&a);
int ans = query(high[a] , 1 , n , 1);
printf("%d\n",ans ? ans : -1);
}
else if(op[0] == 'T')
{
scanf("%d%d",&a,&b);
// printf("a = %d b = %d\n",a,b);
update(high[a] , low[a] , b , 1 , n , 1);
}
}
}
}
/*
1
5
4 3
3 2
1 3
5 2
5
C 3
T 2 1
C 3
T 3 2
C 3
*/