题目链接:点击查看

题目大意:给出一棵有 n 个节点的树,需要执行 m 次操作:

  1. 1 x:点 x 被染色,且随后每一秒染色的区域都会向外扩展一个单位
  2. 2 x:清空所有的染色
  3. 3 x:问点 x 是否被染色

题目分析:因为可以离线,所以考虑按照询问分块,首先用序列自动机求出每次操作后的下一次操作 2,然后分两种情况处理:

  1. 如果两次操作 2 的间隔大于 sqrt( m ),直接暴力 bfs 去模拟,每一块的时间复杂度为 O( n ),均摊之后是 O( sqrt( m ) * n )
  2. 如果两次操作 2 的间隔小于 sqrt( m ),直接 O( m ) 去枚举所有操作 1 ,再 O( m ) 枚举所有操作 3 ,分别计算贡献,均摊之后是 O( sqrt( m ) * sqrt( m ) * sqrt( m ) ) = O( sqrt( m ) * m )

所以总时间复杂度为 O( sqrt( m ) * ( n + m ) )

间隔大于 sqrt( m ) 时直接按照题意 bfs 就行了,这个没有什么技术含量,重点说一下如何处理间隔小于 sqrt( m ) 的操作,对于一个操作 1 和一个操作 3 来说,如果操作 1 会影响到操作 3 的话,那么其在树上的距离一定是小于操作之间的间隔的,这样就转换成距离问题了,预处理一下深度,每次求一下 LCA 就能快速计算了

但是如果是普通的树上倍增或者树链剖分来求 LCA 的话,还要带一个 log,或许也可以通过本题,但最优的方法是用 tarjan 离线 O( n ) 处理出所需要的 lca 然后进行处理,或者用 RMQ 预处理一下,同样可以 O( 1 ) 查询 LCA

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;vector<int>node[N];int op[N],x[N],nt[N],ans[N];bool vis[N];
/*RMQ求LCA*/
int dfn[N],id[N<<1][25],deep[N],cnt,lg2[N<<1];void dfs(int u,int fa,int dep)
{deep[u]=dep;dfn[u]=++cnt;id[cnt][0]=u;for(auto v:node[u]){if(v==fa)continue;dfs(v,u,dep+1);id[++cnt][0]=u;}
}void RMQ()
{for(int i=2;i<=cnt;i++)lg2[i]=lg2[i>>1]+1;for(int j=1;j<=20;j++)for(int i=1;(i+(1<<j)-1)<=cnt;i++){int l=i,r=i+(1<<(j-1));id[i][j]=deep[id[l][j-1]]<deep[id[r][j-1]]?id[l][j-1]:id[r][j-1];}
}int LCA(int x,int y)
{int l=dfn[x],r=dfn[y];if(l>r)swap(l,r);int k=lg2[r-l+1];return deep[id[l][k]]<deep[id[r-(1<<k)+1][k]]?id[l][k]:id[r-(1<<k)+1][k];
}
/*RMQ求LCA*/
int get_dis(int x,int y)
{return deep[x]+deep[y]-2*deep[LCA(x,y)];
}void solve(int l,int r)
{queue<int>q;memset(vis,false,sizeof(vis));for(int i=l;i<=r;i++){int temp=q.size();while(temp--){int u=q.front();q.pop();for(auto v:node[u]){if(vis[v])continue;vis[v]=true;q.push(v);}}if(op[i]==1&&!vis[x[i]]){q.push(x[i]);vis[x[i]]=true;}if(op[i]==3){if(vis[x[i]])ans[i]=true;}}
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n,m;scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs(1,0,0);RMQ();for(int i=1;i<=m;i++)scanf("%d%d",op+i,x+i);nt[m+1]=m+1;for(int i=m;i>=1;i--)//nt[i]:记录第i个位置后再次被重置的位置 {nt[i]=nt[i+1];if(op[i]==2)nt[i]=i;}int b=sqrt(m);for(int i=1;i<=m;i++){if(nt[i]-i>b){solve(i,nt[i]-1);}else{for(int j=i;j<nt[i];j++)//处理每个op==1对每个op==3的贡献 if(op[j]==1)for(int k=j+1;k<nt[i];k++)if(op[k]==3)if(get_dis(x[j],x[k])<=k-j)ans[k]=true; }i=nt[i];}for(int i=1;i<=m;i++)if(op[i]==3)printf("%s\n",ans[i]?"wrxcsd":"orzFsYo");return 0;
}

牛客 - 牛半仙的妹子Tree(按询问分块+RMQ求LCA)相关推荐

  1. 牛客——牛妹与牛牛的游戏

    牛客--牛妹与牛牛的游戏 一天,牛妹找牛牛做一个游戏,牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 1.在当前数字的基 ...

  2. 牛半仙的妹子Tree(Nowcoder)

    题目 牛半仙的妹子的座位呈一个树状结构,由 n 个点和 n−1 条边组成, 1 号结点为根. 当牛半仙的一个妹子无视 牛半仙后,一个单位时间后周围的妹子也会无视牛半仙. 有些时候牛半仙为了吸引妹子们的 ...

  3. 牛客编程巅峰赛:Tree III(BFS or DFS)

    链接:https://ac.nowcoder.com/acm/contest/9557/C 来源:牛客网 题目描述 给出一棵有n个节点的节点标号为1~n的有根树(根为第一个节点,并给出从第2个节点到第 ...

  4. 牛客-牛客练习赛24-B 凤 凰

    链接:https://www.nowcoder.com/acm/contest/157/B 来源:牛客网 题目描述 凤凰于飞,翙翙其羽,亦集爰止. --<诗经·卷阿> 传说,凤凰是百鸟之王 ...

  5. 【牛客】B 烦人的依赖(拓扑排序求顺序)

    链接:https://ac.nowcoder.com/acm/contest/5678/B 来源:牛客网 题目描述 Ubuntu20.04 正式发布了,ZLS 是一个作死小能手,于是他决定尝试一下这个 ...

  6. 牛客-牛客小白月赛6-J 洋灰三角

                                                     J 洋灰三角 链接:https://www.nowcoder.com/acm/contest/136/ ...

  7. 2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/7609/C 题目大意 给出nnn个点的一棵树,mmm个时刻各有一个操作 标记一个点,每个点被标记后的每一个时刻 ...

  8. 牛客 - 牛半仙的妹子图(并查集+bitset/克鲁斯卡尔重构树+主席树)

    题目链接:点击查看 题目大意:给出一个由 n 个点和 m 条边组成的连通图,每个点都有一种颜色,每条边都有一个权值,现在规定一个起点 st,再给出 q 次询问,每次询问给出区间 [ l , r ] , ...

  9. 2021牛客多校4 - Rebuild Tree(树形dp)

    题目链接:点击查看 题目大意:给出一棵 nnn 个节点的树,现在可以删掉 kkk 条边,然后加上 kkk 条边,问有多少种方案使得操作后 nnn 个点仍然是一棵树 题目分析:原树删掉 kkk 条边后会 ...

最新文章

  1. 游戏设计艺术(第3版) The Art of Game Design
  2. 排序算法汇总——转载自http://blog.csdn.net/zhanglong_daniel/article/details/52513058
  3. Linux上操作Docker守护态运行
  4. Java---设计模块(单例的变形)(多例)
  5. 操作系统提供什么服务、如何服务?
  6. MySQL优化四(优化表结构)
  7. 杭电4506小明系列故事——师兄帮帮忙
  8. 软件设计师25-操作系统
  9. Nginx教程1:基本概念
  10. html鼠标各种坐标,各种MOUSE鼠标形状的表示方法
  11. linux raid5 nas,free nas 创建软raid5 来做iscsi服务 1
  12. 06-JavaWEB_Git
  13. 2.C语言基础-sprintf函数用法
  14. linux查看系统内存
  15. 北京邮电大学计算机专业录取名单,祝福!“跪地谢母”考生被北京邮电大学计算机类专业录取...
  16. 408复习策略(强化阶段)
  17. 2024考研《艺术学概论》彭吉象|复习笔记(上篇)(1-6章)
  18. 肝移植笔记1:论文阅读-对率回归预测移植物失功概率
  19. 动力节点『lol版』Java学习路线图(五)Java框架阶段
  20. 动物识别系统 python实现+UI

热门文章

  1. pd 生成mysql语句_PDMan + Navicat Premium + MySQL 数据库设计和工具
  2. java16下载_java lombok下载
  3. linux挂载硬盘读写,mount 挂载第二块硬盘,普通用户可以读写
  4. wordpress archive.php,哪个网址将导致wordpress使用archive.php?
  5. java 生成sql脚本_java导出insert语句并生成sql脚本
  6. Spring Cloud是什么
  7. Nginx的index指令
  8. Nginx系统环境准备
  9. File类概述和构造方法
  10. sqoop增量导入hdfs和导出