【bzoj1905】捉迷藏(线段树)
来源:互联网 发布:深圳美生创谷淘宝地址 编辑:程序博客网 时间:2024/05/16 17:17
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
81 22 33 43 53 66 76 87GC 1GC 2GC 1G
Sample Output
4334
I think
膜岛娘题解
一棵树上两点之间的距离等于该树括号序列中两点间非匹配括号数量之和。将括号序列与房间标号存在一个序列中,用线段树维护五个变量,每个区间用用其所含不匹配的左(b)右(a)括号(a,b)数对表示,l1,l2,r1,r2,dis,分别代表该区间内左端为该区间左端右端为黑点且a’+b’最大的子序列,左端为该区间左端右端为黑点且b’-a’最大的子序列(注意是b’-a’而不是a’-b’),右端为该区间右端且左端为黑点的a’+b’最大的子序列,右端为该区间右端且左端为黑点的a’-b’最大的子序列,区间内最远两点之间的最大距离。
那么维护dis有:
其他变量的维护有些复杂可看岛娘题解自己手推一下……
Code
#include<cmath>#include<cstdio>#include<algorithm>#define M 300000+50#define N 1200000+50#define inf 1e9using 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 - rightminus void 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,rm st[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】捉迷藏(线段树)
- bzoj 1095 捉迷藏(线段树)
- [BZOJ1095][ZJOI2007][线段树]Hide捉迷藏
- BSOJ2381:捉迷藏 括号序列 线段树维护
- bzoj1095 Hide 捉迷藏 括号序列&线段树
- 【线段树】【括号序列】【ZJOI2007】捉迷藏 Hide
- [BZOJ1095]Hide 捉迷藏--括号序列&&线段树
- 【BZOJ1095】【ZJOI2007】捉迷藏 括号序列+线段树维护
- 【BZOJ1095】【ZJOI2007】Hide 捉迷藏 线段树维护括号序列 数据结构的压缩。
- 捉迷藏
- 捉迷藏
- 【BZOJ1095】[ZJOI2007]Hide 捉迷藏【动态树分治】
- [BZOJ1095][ZJOI2007]Hide捉迷藏-动态树分治
- bzoj1095:Hide 捉迷藏(动态树分治)
- BZOJ 1095 ZJOI2007 Hide 捉迷藏 动态树分治+堆
- 【BZOJ 1095】[ZJOI2007]Hide 捉迷藏 动态树分治
- 括号序列 || 动态树分治 bzoj1095【ZJOI2007】Hide 捉迷藏
- bzoj 1095: [ZJOI2007]Hide 捉迷藏 动态树分治+堆
- 2017.07.08【NOIP提高组】模拟赛B组
- Efficient Diffusion on Region Manifolds Recovering Small Objects with Compact CNN Representations
- 关于layui的分页插件的使用
- windows下Mysql5.7.18修改初始密码
- python键盘输入五个数字,判断是否是回文数
- 【bzoj1905】捉迷藏(线段树)
- java 8——Lambda表达式
- 十二、JVM如何利用工具来监控调优前后的性能变化。
- 深入理解Linux内核 第一章笔记
- Jquery ajax异步传值的两个json实用的写法,
- ZJU1024-Calendar Game(模拟)
- java冒泡排序——新人冒泡
- 解决刚安装 ubuntu 16.04 连接不上 wifi 问题
- URDF文件的生成和编写(三)