P4092 [HEOI2016/TJOI2016] 树

P4092 [HEOI2016/TJOI2016] 树

在 2016 年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树,根为 1 ,有以下两种操作:

  1. 标记操作:对某个结点打上标记。(在最开始,只有结点 1 有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)

  2. 询问操作:询问某个结点最近的一个打了标记的祖先。(这个结点本身也算自己的祖先)

你能帮帮她吗?

提示

100% 的数据,1N,Q100000

Solution:

十分好写的题目,我们考虑点亮一个点会带来的影响,显然,点亮一个点只会对其子树产生影响,所以我们先求出这颗子树上的 dfs序 然后记录一下每个点的子树下的 dfs序范围 [stx,edx] . 然后我们就可以按照 dfs序 建一颗线段树。维护一下每个 dfs序区间 的点亮过的点中 dfs序的最大值 ,区间修改单点查询。

然后这题就做完了 。

Code:

#include<bits/stdc++.h>
const int N=1e5+5;
using namespace std;
struct Segmnet_Tree{
struct Tree{
int val;
}t[N<<2];
#define ls x<<1
#define rs x<<1|1
void pushup(int x)
{
t[x].val=max(t[ls].val,t[rs].val);
}
void upd(int x,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)
{
t[x].val=max(t[x].val,k);return;
}
int mid=l+r>>1;
if(L<=mid)upd(ls,l,mid,L,R,k);
if(mid<R)upd(rs,mid+1,r,L,R,k);
}
void query(int x,int l,int r,int pos,int &res)
{
res=max(res,t[x].val);
if(l==r)return;
int mid=l+r>>1;
if(pos<=mid)query(ls,l,mid,pos,res);
else query(rs,mid+1,r,pos,res);
}
}T;
vector<int> E[N];
int n,m,tot;
int rid[N],st[N],ed[N];
void dfs(int x,int fa)
{
st[x]=++tot;rid[tot]=x;
for(auto y : E[x])if(y!=fa)
{
dfs(y,x);
}
ed[x]=tot;
}
char c[10];
void work()
{
cin>>n>>m;
for(int i=2,x,y;i<=n;i++)
{
scanf("%d%d",&x,&y);
E[x].push_back(y);E[y].push_back(x);
}
dfs(1,0);
T.upd(1,1,n,1,n,1);
for(int i=1,x;i<=m;i++)
{
scanf("%s",c);scanf("%d",&x);
if(c[0]=='C')
{
T.upd(1,1,n,st[x],ed[x],st[x]);
}
else
{
int res=0;
T.query(1,1,n,st[x],res);
printf("%d\n",rid[res]);
}
}
}
int main()
{
//freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);
work();
return 0;
}
posted @   liuboom  阅读(1)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验
点击右上角即可分享
微信分享提示