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

题意:给你一个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[n].l=l;
    p[n].r=r;
    p[n].len=r-l+1;
    p[n].flag=0;
    if(l==r)
    {
        if(a[l]=='1')
            p[n].num=0;
        else 
            p[n].num=1;
    }
    else
    {
        int mid=(l+r)/2;
        build(l,mid,n*2);
        build(mid+1,r,n*2+1);
        p[n].num=p[n*2].num+p[n*2+1].num;
    }
}
void pushdown(int n)//往下更新
{
    p[n].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[n].l&&y==p[n].r)
    {
        p[n].flag^=1;
        p[n].num=p[n].len-p[n].num;
    }
    else
    {
        int mid=(p[n].l+p[n].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[n].flag==1)
        pushdown(n);
    if(p[n].l==p[n].r)
    {
        if(p[n].num==1)
        {
            nima=p[n].l;
            if(p[n].l+k-1<=cao)
                update(p[n].l,p[n].l+k-1,1);
        }
    }
    else 
    {
        int mid=(p[n].l+p[n].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;
}
原文地址:https://www.cnblogs.com/jiangjing/p/2943024.html