首页 > 代码库 > vijos1881 闪烁的繁星

vijos1881 闪烁的繁星

描述

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

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

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

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

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

思路:赤裸裸的线段树,这是我做的第三个线段树,当然也是第一个updata比较长的。题意很好懂,但是updata比较的复杂,tree的结构体里要保存左右端点的颜色、最长长度和整个区间的最长长度,然后就是一个个的更新了。

code:

#include<iostream>

#include<cstdio>

using namespace std;

struct use{

int lc,rc,ls,rs,ws;

}tree[10000001];

void updata(int i,int l,int r)

{

int mid;

mid=(l+r)/2;

tree[i].lc=tree[i*2].lc;

tree[i].ls=tree[i*2].ls;

tree[i].rc=tree[i*2+1].rc;

tree[i].rs=tree[i*2+1].rs;

tree[i].ws=max(tree[i*2].ws,tree[i*2+1].ws);

if (tree[i*2].rc!=tree[i*2+1].lc)

{

tree[i].ws=max(tree[i].ws,tree[i*2].rs+tree[i*2+1].ls);

if (tree[i*2].ws==mid-l+1)

  tree[i].ls=tree[i].ls+tree[i*2+1].ls;

if (tree[i*2+1].ws==r-mid)

  tree[i].rs=tree[i].rs+tree[i*2].rs;

}

}

void build(int i,int l,int r)

{

int mid;

if (l==r)

{

tree[i].lc=tree[i].rc=0;

tree[i].ws=tree[i].ls=tree[i].rs=1;

return;

}

mid=(l+r)/2;

build(i*2,l,mid);

build(i*2+1,mid+1,r);

updata(i,l,r);

}

void insert(int i,int l,int r,int k)

{

int mid;

if (l==r&&l==k)

{

tree[i].lc=tree[i].rc=1-tree[i].lc;

return;

}

mid=(l+r)/2;

if (k<=mid) insert(i*2,l,mid,k);

else insert(i*2+1,mid+1,r,k);

updata(i,l,r);

}

int main()

{

int n,q,i,j,k;

scanf("%d%d",&n,&q);

build(1,1,n);

for (i=1;i<=q;++i)

{

  scanf("%d",&k);

  insert(1,1,n,k);

  printf("%d\n",tree[1].ws);

    }

vijos1881 闪烁的繁星