#include <iostream>
#include <cstdio>
using namespace std;
#define maxn 100010
char ch[maxn];
struct Tree
{
int l,r,store,len;
bool lson,rson;
bool flag;
}tree[maxn*3];
void build(int l,int r,int pos)
{
tree[pos].l=l;
tree[pos].r=r;
tree[pos].len=r-l+1;
tree[pos].flag=false;
if(tree[pos].l==tree[pos].r)
{
tree[pos].lson=tree[pos].rson=false;
if(ch[l]=='0')
tree[pos].store=1;
else
tree[pos].store=0;
return;
}
tree[pos].lson=tree[pos].rson=true;
int mid=(l+r)>>1;
build(l,mid,pos*2);
build(mid+1,r,pos*2+1);
tree[pos].store=tree[pos*2].store+tree[pos*2+1].store;
}
void downtree(int i)
{
tree[i].flag=false;
tree[i].store=(tree[i].len-tree[i].store);
if(tree[i].lson) tree[i*2].flag=!tree[i*2].flag;
if(tree[i].rson) tree[i*2+1].flag=!tree[i*2+1].flag;
}
int find(int i)
{
if(tree[i].flag) downtree(i);
if(tree[i].l==tree[i].r)
{
return tree[i].l;
}
if(tree[i].lson&&tree[i*2].flag) downtree(i*2);
if(tree[i].lson&&tree[i*2].store) return find(i*2);
else return find(i*2+1);
}
void Update(int i,int from,int to)
{
if(from<=tree[i].l&&tree[i].r<=to)
{
tree[i].flag=!tree[i].flag;
return;
}
if(tree[i].flag) downtree(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(to<=mid)
{Update(i*2,from,to);}
else if(from>=mid+1)
{Update(i*2+1,from,to);}
else
{
Update(i*2,from,to);
Update(i*2+1,from,to);
}
if(tree[i*2].flag) downtree(i*2);
if(tree[i*2+1].flag) downtree(i*2+1);
tree[i].store=tree[i*2].store+tree[i*2+1].store;
}
int main()
{
int n,k,tot,flag,i,from,to;
while(scanf("%d%d",&n,&k)!=EOF)
{
if(n==0&&k==0) break;
scanf("%s",ch+1);
tot=0;flag=1;
if(k==0)
{
for(i=1;i<=n;i++)
if(ch[i]=='0')
{
break;
}
if(i!=n+1)
{
printf("-1\n");
continue;
}
}
if(k==1)
{
for(i=1;i<=n;i++)
if(ch[i]==0)
tot++;
printf("%d\n",tot);
continue;
}
build(1,n,1);
while(tree[1].store>0)
{
from=find(1);
if(from+k-1>n)
{
flag=0;
break;
}
Update(1,from,from+k-1);
tot++;
}
if(flag)
printf("%d\n",tot);
else
printf("-1\n");
}
return 0;
}
题意:有一个神奇的开关,能把k范围内的0->1 1->0,问最少需要多少个这样的开关,让整个序列变成全1.
因为是跟集合操作有关的,所以想到用线段树。
(1)在建树的时候设一个翻转标记位,更新的时候翻转。
(2)一共三个函数,一个用来翻转,一个用来寻找第一个0位置,一个用来更新(更新从头开始)