HDU 3275 Light (线段树+懒惰标记)

Light
Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

Felicia was given a long string of fancy lanterns, but not all of them are on to light the night. Felicia felt bad about that and he wants to light up all the lanterns. There is a kind of magic switch which can change the states of k continuous lanterns. Once you choose k continuous lanterns and install a switch on them, the states of all k continuous lanterns can be changed together (on ->off or off ->on), but you cannot choose some ones be changed and some ones not be changed. 
Felicia wants to buy as few switches as possible so that he can install them to turn on all the lanterns. Please notice that each switch must control exactly k continuous lanterns. 

Input

The input consists of multiple test cases. The first line of each case contains integers n(0 < n <= 100000), which is the length of that string of fancy lanterns, and k(0 <= k <= n), which is the number of continuous lanterns that a switch will control. The next line consists of a string of “01” with length n. “1” means that lantern is on and “0” means off. Your job is turn all the “0” to “1”. 
The last test case is followed by a line containing two zeros. 

Output

If you cannot finish this job, output “-1” or you should output the minimum number switches that you should buy to turn on all the lanterns.

Sample Input

4 2
0000
4 2
1001
4 2
0110
4 2
0111
0 0

Sample Output

2
1
3
-1



大体意思是说给你两个数。n和m,n是字符串长度,m是连续操作的数目。。然后再给你一个长度为n的字符串。。字符串中只包括‘0’或者‘1’。。然后问你需要几次连续m个的反转才可以把所有的字符反转为‘1’。。如果不能够全部反转为‘1’,,就输出“-1”.。。

重点是对懒惰标记falg 的操作,Update();中,更新到就+1;在pushdown();中,对向下更新的flag +1,而对本身不是直接置0,因为你只是把本次的反转传递下去就OK了。。所以说p[now].flag --;就好了。。或者说直接取等于本身的非也是可以的。。。


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <sstream>
#include <queue>
#include <stack>
#include <functional>
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a));
#define For(a,b) for(int i = a;i<b;i++)
#define LL long long
#define MAX_N 100010
using namespace std;
struct SegmentTree
{
    int l;
    int r;
    int num;
    int num0;
    int flag;
}p[MAX_N<<2];
char x[MAX_N];
void pushup(int now)
{
    p[now].num0 = p[now<<1].num0 + p[now<<1|1].num0;
    p[now].num = p[now<<1].num + p[now<<1|1].num;
    return ;
}
void pushdown(int now)
{
    int tmp = 0,tmp1 = 0;
    if(p[now].l == p[now].r || p[now].flag % 2 == 0) return ;
    tmp = p[now<<1].num0;
    p[now<<1].num0 = p[now<<1].num;
    p[now<<1].num = tmp;
    tmp1 = p[now<<1|1].num0;
    p[now<<1|1].num0 = p[now<<1|1].num;
    p[now<<1|1].num = tmp1;
//    swap(p[now<<1].num,p[now<<1].num0);
//    swap(p[now<<1|1].num,p[now<<1|1].num0);
    p[now<<1].flag += 1;
    p[now<<1|1].flag += 1;
    p[now].flag --;
}
void BuildTree(int root,int l,int r)
{
    p[root].l = l;
    p[root].r = r;
    p[root].flag = 0;
    if(l == r)
    {
        //cout<<l<<' '<<x[l]<<endl;
        if(x[l] == '1')
        {
            p[root].num = 1;
            p[root].num0 = 0;
        }
        else
        {
            p[root].num = 0;
            p[root].num0 = 1;
        }
        return ;
    }
    int mid = (l + r) / 2;
    BuildTree(root<<1,l,mid);
    BuildTree(root<<1|1,mid+1,r);
    pushup(root);
    return ;
}
int Query(int root)
{
    if(p[root].l == p[root].r) return p[root].l;
    pushdown(root);
    int res = -1;
    if(p[root<<1].num0) res = Query(root<<1);
    else if(p[root<<1|1].num0) res = Query(root<<1|1);
    pushup(root);
    return res;
}
void Update(int root,int l,int r)
{
    if(l <= p[root].l && p[root].r <= r)
    {
        int tem2 = 0;
        tem2 = p[root].num;
        p[root].num = p[root].num0;
        p[root].num0 = tem2;
        p[root].flag ++;
        return ;
    }
    pushdown(root);
    int mid = (p[root].l + p[root].r) / 2;
    if(l > mid) Update(root<<1|1,l,r);
    else if(r <= mid) Update(root<<1,l,r);
    else
    {
        Update(root<<1,l,mid);
        Update(root<<1|1,mid + 1,r);
    }
    pushup(root);
    return ;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        if(n==0 && m==0) break;
        getchar();
        scanf("%s",x + 1);
        int len = strlen(x+1);
        BuildTree(1,1,len);
        bool fla = true;
        for(int i = 1; i<=len; i++)
            if(x[i] == '0'){
                fla = false;
                break;
            }
        if(!m)
        {
            if(p[1].num == n)
                cout<<"0"<<endl;
            else cout<<"-1"<<endl;
            continue;
        }
        if(fla)
        {
            cout<<"0"<<endl;
            continue;
        }
        int pos,ans = 0,l,r;
        fla = false;
        while(pos = Query(1))
        {
            //cout<<pos<<endl;
            if(pos == -1) break;
            l = pos;
            r = pos + m - 1;
            if(r > len)
            {
                fla = true;
                break;
            }
            Update(1,l,r);
            ans ++;
        }
        //cout<<ans<<endl;
        if(fla)
            cout<<"-1"<<endl;
        else cout<<ans<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值