博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ 4551][Tjoi2016&Heoi2016]树(并查集)
阅读量:6116 次
发布时间:2019-06-21

本文共 1405 字,大约阅读时间需要 4 分钟。

Description

在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下
两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个
结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖
先)你能帮帮他吗?

Solution

还是非常巧妙的思维

离线,先记录每个点的标记数,倒序处理询问,遇到打标记就把标记数减一,对于标记数为0的点就用并查集与它的父节点合并

#include
#include
#include
#include
#include
#define MAXN 100005using namespace std;int n,q,head[MAXN],cnt=0,f[MAXN],father[MAXN],num[MAXN],sign[MAXN];char opt[MAXN];vector
v;struct Node{ int next,to;}Edges[MAXN*2];void addedge(int u,int v){ Edges[++cnt].next=head[u]; head[u]=cnt; Edges[cnt].to=v;}int read(){ int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); } return x*f;}int find(int x){ if(father[x]==x)return x; return father[x]=find(father[x]);}void dfs(int u){ if(!sign[u])father[u]=find(f[u]); for(int i=head[u];~i;i=Edges[i].next) { int v=Edges[i].to; if(v==f[u])continue; f[v]=u; dfs(v); }}int main(){ memset(head,-1,sizeof(head)); n=read(),q=read(); for(int i=1;i
0;i--) { if(opt[i]=='C') { sign[num[i]]--; if(!sign[num[i]]) father[num[i]]=find(f[num[i]]); } else v.push_back(find(num[i])); } for(int i=v.size()-1;i>=0;i--) printf("%d\n",v[i]); return 0;}

 

转载于:https://www.cnblogs.com/Zars19/p/6872287.html

你可能感兴趣的文章
预处理、const与sizeof相关面试题
查看>>
爬虫豆瓣top250项目-开发文档
查看>>
Elasticsearch增删改查
查看>>
oracle归档日志增长过快处理方法
查看>>
有趣的数学书籍
查看>>
teamviewer 卸载干净
查看>>
多线程设计模式
查看>>
解读自定义UICollectionViewLayout--感动了我自己
查看>>
SqlServer作业指定目标服务器
查看>>
UnrealEngine4.5 BluePrint初始化中遇到编译警告的解决办法
查看>>
User implements HttpSessionBindingListener
查看>>
抽象工厂方法
查看>>
ubuntu apt-get 安装 lnmp
查看>>
焊盘 往同一个方向增加 固定的长度方法 总结
查看>>
eclipse的maven、Scala环境搭建
查看>>
架构师之路(一)- 什么是软件架构
查看>>
jquery的冒泡和默认行为
查看>>
USACO 土地购买
查看>>
【原创】远景能源面试--一面
查看>>
B1010.一元多项式求导(25)
查看>>