题意:

nnn 个点的一棵树,每个点初始为 000,支持两种操作,第一种操作 CxC \ xC x,表示将第 xxx 个点取反,即 111 变 000,000 变 111。第二种操作为 GGG,表示查询两个相距最远的 000 点距离。(1≤n≤105,1≤m≤5∗105)(1\leq n\leq 10^5,1\leq m\leq 5*10^5)(1≤n≤105,1≤m≤5∗105)


思路:

这道题的做法有括号序列、动态点分治、线段树维护直径。此处只介绍线段树维护直径的做法。

首先我们求一个 dfsdfsdfs 序,然后在 dfsdfsdfs 序上建线段树,对于线段树的每个区间,我们维护两个点表示在这个区间中相距最远的两个 000 点。区间合并时我们只需要取出这两个区间所维护的点,然后对这四个点两两求距离更新答案即可。

这样做的原因在于对于两个子树来说,每个子树都有一条属于该子树的直径,则两个子树合并后的新直径必定是从原来两个子树中的 444 个点中选取 222 个点作为答案。

大致思路就是这样,具体细节见代码。


代码:

#include <bits/stdc++.h>
#define rep(i,a,b) for(int i = a; i <= b; i++)
typedef long long ll;
const int N = 1e5+100;
using namespace std;int n,m,dis[N],tot,head[N],f[N][25],dfn[N],rk[N],flag[N],T;
pair<int,int> sgt[4*N];
struct Edge{int to,next;
}e[2*N];inline void add(int x,int y){e[++tot].to = y, e[tot].next = head[x], head[x] = tot;
}void dfs(int x,int fa){dis[x] = dis[fa]+1; f[x][0] = fa; dfn[x] = ++tot; rk[tot] = x;for(int i = 1; (1<<i) <= dis[x]; i++)f[x][i] = f[f[x][i-1]][i-1];for(int i = head[x]; i; i = e[i].next){int y = e[i].to;if(y == fa) continue;dis[y] = dis[x]+1; dfs(y,x);}
}inline int lca(int x,int y){if(dis[x] > dis[y]) swap(x,y);for(int i = T; i >= 0; i--)if(dis[f[y][i]] >= dis[x]) y = f[y][i];if(x == y) return x;for(int i = T; i >= 0; i--)if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];return f[x][0];
}inline int dist(int x,int y){if(x == 0 && y == 0) return -1;if(x == 0 || y == 0) return 0;return dis[x]+dis[y]-2*dis[lca(x,y)];
}inline pair<int,int> pushUp(pair<int,int> x,pair<int,int> y){int a[5],res = 0,cnt = 0,tmp; pair<int,int> base = make_pair(0,0); a[0] = 0;if(x.first && flag[x.first]) a[++cnt] = x.first;if(x.second && flag[x.second]) a[++cnt] = x.second;if(y.first && flag[y.first]) a[++cnt] = y.first;if(y.second && flag[y.second]) a[++cnt] = y.second;rep(i,1,cnt-1)rep(j,i+1,cnt)if((tmp=dist(a[i],a[j])) > res)res = tmp, base = make_pair(a[i],a[j]);if(res == 0) base = make_pair(a[cnt],a[cnt]);return base;
}inline void build(int now,int l,int r){if(l == r) sgt[now] = make_pair(rk[l],rk[l]), flag[rk[l]] = 1;else{int mid = (l+r)>>1;build(now<<1,l,mid); build(now<<1|1,mid+1,r);sgt[now] = pushUp(sgt[now<<1],sgt[now<<1|1]);}
}inline void update(int now,int l,int r,int pos){if(l == r){flag[rk[l]] ^= 1;if(flag[rk[l]]) sgt[now] = make_pair(rk[l],rk[l]);else sgt[now] = make_pair(0,0);return;}int mid = (l+r)>>1;if(pos <= mid) update(now<<1,l,mid,pos);else update(now<<1|1,mid+1,r,pos);sgt[now] = pushUp(sgt[now<<1],sgt[now<<1|1]);
}int main()
{scanf("%d",&n); tot = 1; T = (int)(log(n)/log(2))+1;rep(i,1,n-1){int a,b; scanf("%d%d",&a,&b);add(a,b); add(b,a);}tot = 0; dfs(1,0); build(1,1,n);scanf("%d",&m);while(m--){char op[10]; scanf("%s",op);if(op[0] == 'C'){int x; scanf("%d",&x); update(1,1,n,dfn[x]);}else printf("%d\n",dist(sgt[1].first,sgt[1].second));}return 0;
}

【BZOJ-1095】[ZJOI2007] Hide 捉迷藏【线段树维护树直径】相关推荐

  1. [BZOJ 1095] [ZJOI2007]Hide 捉迷藏——线段树+括号序列(强..)

    神做法-%dalao,写的超详细 konjac的博客. 如果觉得上面链接的代码不够优秀好看,欢迎回来看本蒟蒻代码- CODE WITH ANNOTATION 代码中−6-6−6表示左括号'[',用−9 ...

  2. bzoj 1095: [ZJOI2007]Hide 捉迷藏

    Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条 ...

  3. 【BZOJ 1095】 1095: [ZJOI2007]Hide 捉迷藏 (括号序列+线段树)

    1095: [ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游 ...

  4. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

  5. 1095: [ZJOI2007]Hide 捉迷藏

    发现动态树分治还是挺好玩的.......然而效率有点拙计 跑了14S多,差点以为要TLE,回头一看发现时限40S. 模板抄的PoPoQQQ大爷的,顺便看了下漆神的论文,各种吓Cry. 准备水下QTRE ...

  6. [ZJOI2007]Hide 捉迷藏

    [ZJOI2007]Hide 捉迷藏 小岛的博客 黄学长的博客 NOI08 冬令营论文 <数据结构的提炼与压缩> 这个问题竟然还能用线段树做,拿小本本记下来. 转载于:https://ww ...

  7. BZOJ1095 ZJOI2007 Hide 捉迷藏

    BZOJ1095 ZJOI2007 Hide 捉迷藏 动态树分治+堆 动态点分治 posted on 2016-06-25 11:35  wjyi 阅读( ...) 评论( ...) 编辑 收藏 转载 ...

  8. [ZJOI2007]Hide 捉迷藏(数据结构)

    LCT QTree也行吧. 思路巧妙,速度颠覆人们对LCT的常识. 发现set.find找不到会返回end(),然后你就把他给删了,这会导致在之后的插入时爆炸. 边权下放点权,upd时要小心. 和其他 ...

  9. 「BZOJ1095」[ZJOI2007] Hide 捉迷藏

    题目描述 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩捉迷藏游戏.他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条 ...

最新文章

  1. 查看Entity Framework生成的SQL语句
  2. 2013秋东北计算机在线作业,2013秋奥鹏东北师范大学计算机应用基础第三次在线作业及答案.doc...
  3. 聊聊 Redis 使用场景
  4. couldn't register *** with the bootstrap server. Error: unknown error code.
  5. Spring-Spring整合MyBatis详解
  6. ActiveMQ入门-ActiveMQ环境搭建
  7. java命令主动清空jvm_JVM史上最全实践优化没有之一
  8. extractCSS – 帮助你从 HTML 中快速分离出 CSS
  9. Javaweb MVC设计模式、Modle发展史、项目分层和三层架构
  10. Pytorch:RuntimeError: DataLoader worker (pid 27) is killed by signal: Killed. Details are lost due
  11. 小霸王被申请破产重整;虎牙员工自曝被HR抬出公司;Office 2010被微软终止服务|极客头条
  12. vs2005环境的一些快捷键
  13. python和java哪个好学-java和python哪个的前途更好?
  14. 大家知道,我的废话很多,所以来凑热闹
  15. 前端项目总结与分享(PPT整理)
  16. python 安装whl文件
  17. TeX Live 2021 从卸载到安装指南
  18. Mysql(免安装版)安装、配置、卸载与更改端口
  19. 基于fastadmin的工业园区科技园水电费管理系统
  20. 中职计算机技能,中职计算机专业技能竞赛规则

热门文章

  1. linux下制作windows u盘启动盘,Ubuntu下制作windows U盘启动盘
  2. java中super()什么意思_java中Super到底是什么意思?必须举例说明!
  3. iframe结构的网站按F5刷新子页面的实现方式
  4. 时间序列(time serie)分析系列之SARIMAX预测与异常诊断3
  5. thinkphp中的setInc、setDec方法
  6. 雨滴蜂窝常用文件标识符
  7. SQL Server外键约束
  8. try - with - resources详解
  9. 【LOJ6681】yww 与树上的回文串(点分治)(AC自动机)(字符串哈希)(回文串broder理论)
  10. Wapiti是什么以及使用教程