码迷,mamicode.com
首页 > 其他好文 > 详细

Vijos1881闪烁的繁星 [线段树]

时间:2016-10-09 00:04:28      阅读:198      评论:0      收藏:0      [点我收藏+]

标签:

P1881闪烁的繁星 

背景

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

描述

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

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

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

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

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

格式

输入格式

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

输出格式

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

样例1

样例输入1[复制]

6 2
2
4

样例输出1[复制]

3
5

限制

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

提示

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


 

有点像动态最大连续和

记录区间最大长度,前缀最大长度和后缀最大长度

merge时考虑左右区间能不能连在一起

//
//  main.cpp
//  vijos1881
//
//  Created by Candy on 10/8/16.
//  Copyright © 2016 Candy. All rights reserved.
//

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define m (l+r)/2
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define lc o<<1
#define rc o<<1|1
const int N=2e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<0||c>9){if(c==-)f=-1;c=getchar();}
    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
    return x*f;
}
int n,Q,x,a[N];
struct node{
    int ans,pre,suf;
}t[N<<2];
void merge(int o,int u,int l1,int r1,int v,int l2,int r2){
    if(a[r1]!=a[l2]&&t[u].pre==l2-l1)
        t[o].pre=l2-l1+t[v].pre;
    else t[o].pre=t[u].pre;
    if(a[r1]!=a[l2]&&t[v].suf==r2-r1)
        t[o].suf=r2-r1+t[u].suf;
    else t[o].suf=t[v].suf;
    t[o].ans=max(t[u].ans,t[v].ans);
    if(a[r1]!=a[l2])
        t[o].ans=max(t[o].ans,t[u].suf+t[v].pre);
}
void build(int o,int l,int r){
    if(l==r) t[o].ans=t[o].pre=t[o].suf=1;
    else{
        build(lson);
        build(rson);
        merge(o,lson,rson);
    }
}
void update(int o,int l,int r,int p){//printf("up %d %d %d\n",o,l,r);
    if(l==r) a[p]^=1;
    else{
        if(p<=m) update(lson,p);
        else update(rson,p);
        merge(o,lson,rson);
    }
}
int main(int argc, const char * argv[]) {
    n=read();Q=read();
    build(1,1,n);
    for(int i=1;i<=Q;i++){
        x=read();
        update(1,1,n,x);
        printf("%d\n",t[1].ans);
    }
    
    return 0;
}

 

Vijos1881闪烁的繁星 [线段树]

标签:

原文地址:http://www.cnblogs.com/candy99/p/5940569.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!