Description

捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的距离。

Input

 第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如上文所示。

Output

 对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关着灯的,输出0;若所有房间的灯都开着,输出-1。

Sample Input

8
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G

Sample Output

4
3
3
4

I think

膜岛娘题解
    一棵树上两点之间的距离等于该树括号序列中两点间非匹配括号数量之和。将括号序列与房间标号存在一个序列中,用线段树维护五个变量,每个区间用用其所含不匹配的左(b)右(a)括号(a,b)数对表示,l1,l2,r1,r2,dis,分别代表该区间内左端为该区间左端右端为黑点且a’+b’最大的子序列,左端为该区间左端右端为黑点且b’-a’最大的子序列(注意是b’-a’而不是a’-b’),右端为该区间右端且左端为黑点的a’+b’最大的子序列,右端为该区间右端且左端为黑点的a’-b’最大的子序列,区间内最远两点之间的最大距离。
    那么维护dis有:

dis[i]=Max(dis[i<<1],  dis[i<<1|1],  r1i<<1+l2i<<1|1,  r2i<<1+l1i<<1|1

dis[i]=Max(dis[i
    其他变量的维护有些复杂可看岛娘题解自己手推一下……

Code

#include<cmath>
#include<cstdio>
#include<algorithm>
#define M 300000+50
#define N 1200000+50
#define inf 1e9
using namespace std;
int n,q,x,y,s,t,sum;
int c[M],h[M],to[M],nxt[M],pos[M],lgh[M];
// lgh[i] 房间i关灯 c[]包含括号与房间灯的序列 pos[i] 房间i在c[]中对应的编号
struct node {int lp,rp,lm,rm,a,b,dis;//lp - leftplus rm - rightminusvoid inicial(int x) {dis=-inf;a=b=0;if(c[x]==-1) b=1; //b代表区间左括号数if(c[x]==-2) a=1;//a代表区间右括号数if(c[x]>0&&lgh[c[x]]) lp=rp=lm=rm=0; //灯是关着的else lp=rp=lm=rm=-inf;}
}st[N];
int Max(int x,int y) { return x>y?x:y; }
char ch;
void read(int &x) {x=0,ch=getchar();while(ch>'9'||ch<'0')ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
}
void add(int x,int y) {to[++s]=y,nxt[s]=h[x],h[x]=s;to[++s]=x,nxt[s]=h[y],h[y]=s;
}
void dfs(int x,int fa) {c[++t]=-1;c[pos[x]=++t]=x;//最开始所有的灯都是关着的for(int i=h[x];i;i=nxt[i]) {if(to[i]==fa)continue;dfs(to[i],x);}c[++t]=-2;
}
void update(int k) {int ls=k<<1,rs=k<<1|1;int a=st[ls].a,b=st[ls].b,c=st[rs].a,d=st[rs].b;st[k].dis=Max(st[ls].dis,st[rs].dis);//更新区间最大值st[k].dis=Max(st[k].dis,Max(st[ls].rp+st[rs].lm,st[ls].rm+st[rs].lp));//跨中间的两段合并 保证两端都有黑点if(b>=c) st[k].a=a,st[k].b=b-c+d;//更新当前区间左右括号数else st[k].a=a+c-b,st[k].b=d;st[k].rp=Max(st[rs].rp,Max(st[ls].rp-c+d,st[ls].rm+c+d));//更新lp,rp,lm,rmst[k].lp=Max(st[ls].lp,Max(st[rs].lp+a-b,st[rs].lm+a+b));st[k].rm=Max(st[rs].rm,st[ls].rm+c-d);st[k].lm=Max(st[ls].lm,st[rs].lm+b-a);//leftminus维护的是max{b-a|S’(a,b)是S的一个前缀,且有一个黑点紧接在S之后}
}
void build(int k,int l,int r) {if(l==r) { st[k].inicial(l); return; }int m=(l+r)>>1;build(k<<1,l,m);build(k<<1|1,m+1,r);update(k);
}
void modify(int k,int l,int r,int pos) {if(l==r) { st[k].inicial(l); return; }int m=(l+r)>>1;if(pos<=m) modify(k<<1,l,m,pos);else modify(k<<1|1,m+1,r,pos);update(k);
}
int main() {read(n),sum=n;for(int i=1;i<=n;++i) lgh[i]=1;for(int i=1;i<n;++i)read(x),read(y),add(x,y);dfs(1,0);build(1,1,t);read(q);while(q--) {ch=getchar();if(ch=='C') {read(x);if(!lgh[x]) ++sum;//sum记关灯数else --sum;lgh[x]^=1;modify(1,1,t,pos[x]);}else {if(sum==1)puts("0");else if(sum==0)puts("-1");else printf("%d\n",st[1].dis);ch=getchar();}}return 0;
}

【bzoj1905】捉迷藏(线段树)相关推荐

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

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

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

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

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

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

  4. 2019.03.21【ZJOI2007】【BZOJ1095】【洛谷P2056】Hide 捉迷藏(DFS序)(线段树)

    BZOJ传送门 洛谷传送门 解析: 其实就是QTREE4的弱化版,可以直接用QTREE4的解法来做. 但是这道题有优秀的O(nlog⁡n)O(n\log n)O(nlogn)做法. 我们考虑利用DFS ...

  5. 【BZOJ-1095】[ZJOI2007] Hide 捉迷藏【线段树维护树直径】

    题意: nnn 个点的一棵树,每个点初始为 000,支持两种操作,第一种操作 CxC \ xC x,表示将第 xxx 个点取反,即 111 变 000,000 变 111.第二种操作为 GGG,表示查 ...

  6. 二逼平衡树——树套树(线段树套Splay平衡树)

    题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...

  7. 线段树——HDU - 1698

    题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...

  8. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  9. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

最新文章

  1. JVM面试问题系列:JVM 配置常用参数和常用 GC 调优策略
  2. 简单的openssh自动升级脚本
  3. 乘法运算-快速傅里叶变换
  4. Github+jsDelivr为脚本/图片等静态文件加速的全球CDN
  5. 倦怠和枯燥_我如何艰难地学习倦怠
  6. 在Html5中与服务器交互
  7. 利用google网管工具,快速诊断网站(一)
  8. QT IDE下载及安装(最新版本)
  9. react-pdf预览pdf
  10. mod mpm event php7.1,CentOS 7 安裝 PHP-FPM 及使用 mod_mpm_event
  11. 嵌入式编程经典书籍推荐
  12. 微服务选择Spring Cloud还是Dubbo?
  13. 将渲染计算搬到云端,开启低成本、强交互、沉浸式体验
  14. 编译原理实验三【中间代码生成程序设计】
  15. win10系统更新完部分电脑亮度无法调节或者找不到模块
  16. 前序遍历+中序遍历重建二叉树
  17. mysql 通过load data local infile导入txt文件数据
  18. 中国大学MOOC课程信息之数据分析可视化一
  19. kali翻译插件_Kali优化之安装翻译工具goldendict及使用方法
  20. EZDML 3.23 快速生成数据界面原型

热门文章

  1. 精华文章置顶--CDC系列之一 :使用Dejournal Filter在InterSystems IRIS/Caché上通过Mirroring实现CDC功能...
  2. 一款开源的PHP邮箱系统
  3. 如何注册Line账号?-Line账号/Line广告/Line好友
  4. 网络受限_受限人工神经网络对幸福的追求
  5. 单片机输入和输出模式简要说明
  6. git push时rejected,解决non-fast-forward errors的办法
  7. gethostbyname和struct hostent详解
  8. Sourcetree 拉取代码提示填写 authentic,但配置无法更改用户
  9. 5G+边缘计算 物联网嵌入式边缘计算平台
  10. Debug 武侠世界