您的位置:首页 > 其它

hdu 3275(线段树的延迟标记,我被坑了)

2013-03-04 16:55 363 查看
题意:给你一个n(代表n个0或者1)和k(一次可以更新k个数),问把它们全部变成1至少需要多少步,如果无法实现则输出-1。

思路:此题用到了贪心的思想,通过举例可以发现:从左边开始一碰到0就更新一次是最优解;然后接下来的是线段树的延迟标记,但是坑爹的是:我的数组开了100005*4一直是Runtime Error,后来改了100005*6之后才AC了,中间花费了我好多时间去查错,气死我了!!!

代码实现:

#include<iostream>
#include<cstring>
using namespace std;
struct node{
int num;
int flag;
int l;
int r;
int len;
}p[100005*6];//坑爹的数组
int n,k,nima,cao;
char a[100005];
void build(int l,int r,int n)//建树
{
p
.l=l;
p
.r=r;
p
.len=r-l+1;
p
.flag=0;
if(l==r)
{
if(a[l]=='1')
p
.num=0;
else
p
.num=1;
}
else
{
int mid=(l+r)/2;
build(l,mid,n*2);
build(mid+1,r,n*2+1);
p
.num=p[n*2].num+p[n*2+1].num;
}
}
void pushdown(int n)//往下更新
{
p
.flag=0;
p[n*2].flag^=1;
p[n*2+1].flag^=1;
p[n*2].num=p[n*2].len-p[n*2].num;
p[n*2+1].num=p[n*2+1].len-p[n*2+1].num;
}
void update(int x,int y,int n)//更新操作
{
if(x==p
.l&&y==p
.r)
{
p
.flag^=1;
p
.num=p
.len-p
.num;
}
else
{
int mid=(p
.l+p
.r)/2;
if(x>mid)
update(x,y,n*2+1);
else if(y<=mid)
update(x,y,n*2);
else
{
update(x,mid,n*2);
update(mid+1,y,n*2+1);
}
}
}
void insert(int x,int n)//查找0的位置,nima返回的也是0的位置,如果nima=0,则说明全是1了
{
if(nima)
return ;
if(p
.flag==1)
pushdown(n);
if(p
.l==p
.r)
{
if(p
.num==1)
{
nima=p
.l;
if(p
.l+k-1<=cao)
update(p
.l,p
.l+k-1,1);
}
}
else
{
int mid=(p
.l+p
.r)/2;
if(x>mid)
insert(x,n*2+1);
else
{
insert(x,n*2);
insert(mid+1,n*2+1);
}
}
}
int main()
{
int temp,t;
while(scanf("%d%d",&n,&k)!=EOF&&(n!=0||k!=0))
{
cao=n;
temp=0;
t=0;
getchar();
scanf("%s",a+1);
build(1,n,1);
if(p[1].num==0)
{
printf("0\n");
continue;
}
if(k==0)//特殊情况
{
printf("-1\n");
continue;
}
while(1)
{
nima=0;
insert(temp+1,1);
temp=nima;
if(nima==0)
break;
if(n-temp+1<k)
break;
t++;
}
if(nima==0)
printf("%d\n",t);
else
printf("-1\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: