1881闪烁的繁星——线段树vijos

对于这道题  是一道裸线段树  从单点修改 全局查询 一眼看出线段树。。O(∩_∩)O~

只不过这道题相较于原线段树  多了一个判定  
即当tree[i]的左儿子  右儿子 的中间部分可以相连接构成一个更大的序列时的特判

可以开一个数组a[i]记录当前点的明灭状况  -1为明  1为灭   每次改变状态就是a[i]*=-1;

若左儿子右端点为 r    右儿子左端点为 l
当a[l]+a[r]==0
则可以连接   
则父节点的maxlong  为  左儿子的maxlong   右儿子的maxlong  中间连接后的长度 中的最大值
并更新 父节点的   左起长度   右起长度  (这部分原理以及做法就自己想吧)

然后就递归了



 

背景

繁星闪烁着--深蓝的太空
何曾听得见他们对语
沉默中
微光里
他们深深的互相颂赞了

描述

繁星, 漫天的繁星.
繁星排成一列, 我数一数呀, 一共有N只小星星呢.

星星们是听话的好孩子, 小岛在指挥它们跳舞呢.
舞蹈开始前, 它们都亮了起来!

小岛指一指第i只小星星, 只见第i只小星星立刻改变了自己的状态.
如果它之前是亮着的, 那么立刻就灭掉了.
如果它之前是灭掉的, 现在就立刻亮了呀!

如果说, 可以有连续若干只小星星.
其中任意相邻两只星星状态不同.
那就是最美的了.

小岛希望知道:
每一次发出指令之后
能找到最长的连续小星星, 满足上述需求的
有多长?

格式

输入格式

第一行有两个整数, 分别为星星总数N, 和指令总数Q.
1<=N<=200,000; 1<=Q<=200,000.
之后Q行, 每行有一个整数i: 1<=i<=N, 表示小岛发出的指令.

输出格式

输出有Q行, 其中每i行有一个整数.
表示小岛的第i条指令发出之后, 可以找到的满足要求的最长连续星星序列有多长?

样例1

样例输入1[复制]

6 224

样例输出1[复制]

35

限制

对于20%的数据: N, Q <= 100.
对于30%的数据: N, Q <= 70000.
对于100%的数据: 1 <= N, Q <= 200,000.

提示

对于样例, 星星序列的状态依次为: OOOOOO -> OXOOOO -> OXOXOO
这里用O表示亮着的星星, 用X表示灭掉的星星.

#include<iostream>
#include<cstdio>
#include<cstring> 
#define MAXN 200000+10
using namespace std;
int a[200000+10];
struct node
{
<span style="white-space:pre">	</span>int l,r;
<span style="white-space:pre">	</span>int maxlong;
<span style="white-space:pre">	</span>int leftlong;
<span style="white-space:pre">	</span>int rightlong;
<span style="white-space:pre">	</span>node()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>maxlong=1;
<span style="white-space:pre">		</span>leftlong=1;
<span style="white-space:pre">		</span>rightlong=1;
<span style="white-space:pre">	</span>}
}tree[800000+10];
int n,q;
int readdata()
{
<span style="white-space:pre">	</span>scanf("%d%d",&n,&q);
}
void build(int l,int r,int m)
{
<span style="white-space:pre">	</span>tree[m].l=l;
<span style="white-space:pre">	</span>tree[m].r=r;
<span style="white-space:pre">	</span>if(l==r)
<span style="white-space:pre">	</span>return;
<span style="white-space:pre">	</span>int mid=(l+r)/2;
<span style="white-space:pre">	</span>build(l,mid,2*m);
<span style="white-space:pre">	</span>build(mid+1,r,2*m+1);<span style="white-space:pre">	</span>
}
void change(int m,int c)
{
<span style="white-space:pre">	</span>if(tree[m].l==tree[m].r&&tree[m].l==c)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>a[c]*=-1;
<span style="white-space:pre">		</span>return;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>int ll=tree[m].l;
<span style="white-space:pre">	</span>int rr=tree[m].r;
<span style="white-space:pre">	</span>int mid=(ll+rr)/2;
<span style="white-space:pre">	</span>if(c<=mid)
<span style="white-space:pre">	</span>change(m*2,c);
<span style="white-space:pre">	</span>else change(m*2+1,c);
<span style="white-space:pre">	</span>if(a[tree[2*m].r]+a[tree[2*m+1].l]==0)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>tree[m].maxlong=max(tree[2*m].rightlong+tree[2*m+1].leftlong,tree[2*m+1].maxlong);
<span style="white-space:pre">		</span>tree[m].maxlong=max(tree[m].maxlong,tree[2*m].maxlong);<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span>if(tree[2*m].leftlong==tree[2*m].r-tree[2*m].l+1)
<span style="white-space:pre">		</span>tree[m].leftlong=tree[2*m].leftlong+tree[2*m+1].leftlong;
<span style="white-space:pre">		</span>else tree[m].leftlong=tree[2*m].leftlong;<span style="white-space:pre">			</span>
<span style="white-space:pre">		</span>if(tree[2*m+1].rightlong==tree[2*m+1].r-tree[2*m+1].l+1)
<span style="white-space:pre">		</span>tree[m].rightlong=tree[2*m+1].rightlong+tree[2*m].rightlong;
<span style="white-space:pre">		</span>else tree[m].rightlong=tree[2*m+1].rightlong;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>else
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>tree[m].maxlong=max(tree[2*m].maxlong,tree[2*m+1].maxlong);
<span style="white-space:pre">		</span>tree[m].leftlong=tree[2*m].leftlong;
<span style="white-space:pre">		</span>tree[m].rightlong=tree[2*m+1].rightlong;
<span style="white-space:pre">	</span>}<span style="white-space:pre">	</span>
}
void work()
{
<span style="white-space:pre">	</span>int co=0;
<span style="white-space:pre">	</span>for(int i=1;i<=q;i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>scanf("%d",&co);
<span style="white-space:pre">		</span>change(1,co);
<span style="white-space:pre">		</span>printf("%d\n",tree[1].maxlong);
<span style="white-space:pre">	</span>}
}
int main()
{
<span style="white-space:pre">	</span>memset(a,-1,sizeof(a));
<span style="white-space:pre">	</span>readdata();
<span style="white-space:pre">	</span>build(1,n,1);
<span style="white-space:pre">	</span>work();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值