首页 > 代码库 > 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 闪烁的繁星