题意:给一些节点简单额对应关系,可以组成一个树,如果树的某一个节点更新那么他的所有子节点都要更新,中间,会有一些查询
分析:题意倒也不难理解,但是但是不知道怎么建树。。。于是自能百度,看了kuangbin大神的博客豁然开朗,可以用每个节点的所包含的子节点段来当做线段树的节点,查找每个节点所包含的段可以用简单的DFS实现。
*************************************************************************
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std; const int MAXN = ; int Start[MAXN], End[MAXN];//每个员工所有下属的开始和结束节点,包含本身
int index;//DFS用记录节点的编号
vector<int> G[MAXN];//保存边 void DFS(int k)
{
Start[k] = ++index;
for(int i=,len=G[k].size(); i<len; i++)
DFS(G[k][i]);
End[k] = index;
} struct SegmentTree
{
int L, R, task;
bool isCover;
int Mid(){return (L+R)/;}
}a[MAXN*]; void BuildTree(int r, int L, int R)
{
a[r].L = L, a[r].R = R;
a[r].task = -, a[r].isCover = false; if(L == R)return ; BuildTree(r<<, L, a[r].Mid());
BuildTree(r<<|, a[r].Mid()+, R);
}
void Down(int r)
{
if(a[r].L != a[r].R && a[r].isCover)
{
a[r<<].isCover = a[r<<|].isCover = true;
a[r<<].task = a[r<<|].task = a[r].task;
a[r].isCover = false;
}
}
void Insert(int r, int L, int R, int task)
{
Down(r); if(a[r].L == L && a[r].R == R)
{
a[r].isCover = true;
a[r].task = task;
return ;
} if(R <= a[r].Mid())
Insert(r<<, L, R, task);
else if(L > a[r].Mid())
Insert(r<<|, L, R, task);
else
{
Insert(r<<, L, a[r].Mid(), task);
Insert(r<<|, a[r].Mid()+, R, task);
}
}
int Query(int r, int k)
{
Down(r); if(a[r].L == a[r].R)
return a[r].task; if(k <= a[r].Mid())
return Query(r<<, k);
else
return Query(r<<|, k);
} int main()
{
int T, t=; scanf("%d", &T); while(T--)
{
int i, N, M, u, v; char s[]; scanf("%d", &N); for(i=; i<=N; i++)
G[i].clear();
bool use[MAXN] = {};
for(i=; i<N; i++)
{
scanf("%d%d",&u, &v);
G[v].push_back(u);
use[u] = true;
} index = ;
for(i=; i<=N; i++)if(!use[i]){
DFS(i); break;} BuildTree(, , N);
printf("Case #%d:\n", t++); scanf("%d", &M); while(M--)
{
scanf("%s", s); if(s[] == 'C')
{
scanf("%d", &u);
printf("%d\n", Query(, Start[u]));
}
else
{
scanf("%d%d", &u, &v);
Insert(, Start[u], End[u], v);
}
}
} return ;
}