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. 【组队学习】【27期】Java编程语言
  2. IDC_ Pro_Env _CentOS 5.4_Open×××
  3. Fragment与FragmentActivity的关系
  4. PL/SQL Developer中如何格式化SQL
  5. ueditor 编辑html文件名,UEditor编辑器自定义上传图片或文件路径的修改方法,ueditor修改方法...
  6. SpringCloud 入门教程(八): 断路器指标数据监控Hystrix Dashboard 和 Turbine
  7. visio绘图固定图形位置
  8. [转]关于PSP的3.52 M33-2自制系统七大热点问题
  9. PN5180射频识别芯片学习笔记
  10. 一个在线挑选编程字体的网站
  11. Python爬虫实战|爬取视频
  12. 关于java开发阿里云视频直播的使用及掉坑、爬坑,欢迎入坑交流
  13. pytho的虚拟环境
  14. freesurfer recon-all并行运算parallel
  15. blp和biba属于哪种访问控制_CISP官方信息安全技术章节练习二
  16. oracle rfs进程过多,【DB笔试面试755】在Oracle的DG中,RFS、LNSn、MRP、LSP进程的作用分别是什么?...
  17. 国内固定电话和传真的正则表达式
  18. 初级测试工程师要求(零基础必备)
  19. 图片压缩-speedpdf免费无损在线压缩图片
  20. 代码坏的味道07:依恋情结(Feature Envy)

热门文章

  1. 关于Attention的超详细讲解
  2. 从0开始学习 GitHub 系列之「04.向GitHub 提交代码」----转载自stormzhang 原创文章
  3. C51流水灯由开关控制自下而上自上而下的实验
  4. 力扣(1053.115)补9.13
  5. go语言学习-- chan与goroutine
  6. Java-小写字母转换大写字母
  7. burp抓包mumu模拟器
  8. html 图片自动滚动播放,CSS3实现图片滚动播放效果
  9. 小学计算机打字基础知识教案绿色圃,小学信息技术《键盘操作再加强—认识特殊键》教案...
  10. 用Jsp开发wap应用