hdu4614Vases and Flowers(线段树+二分)

题目描述:

Vases and Flowers

Problem Description
  Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.
 
题目大意:给一个序列长度的花盆,两种操作,操作1:输入a,k,从a-n中没有放置空花盆中从左到右放置最多k躲花,并返回防止的第一个位置和最后一个位置
操作2:输入a,b,将a-b区间中的所有花清除,并返回清除的个数
思路:操作2很好解决,属于常规线段树操作,操作1需要找到防止的第一个位置和最后一个位置,我们可以用二分的方法不停判断区间的sum来找出来,
大家一定要把代码模块化,一个函数一个功能,不然真的很难debug,我知道二分但是还调了好久,就是因为代码太乱...
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 55000;
const int inf = 0x3f3f3f3f;
#define ls(x) x<<1
#define rs(x) x<<1|1
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
int last[maxn << 2], tag[maxn << 2];
//剩余位置数量和懒标记
int n, m;
void build(int rt, int l, int r) {
    last[rt] = (r - l + 1); tag[rt] = -1;
    if (l == r) {
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
}
void push_up(int rt) {
    last[rt] = last[ls(rt)] + last[rs(rt)];
}
void push_down(int rt,int l,int r) {
    if (l == r)return;
    int m = r - l + 1;
    if (tag[rt] != -1) {//如果需要下推
        last[ls(rt)] = tag[rt] * ((m + 1) / 2);
        last[rs(rt)] = tag[rt] * (m / 2);
        tag[ls(rt)] = tag[rt];
        tag[rs(rt)] = tag[rt];
        tag[rt] = -1;
    }
}
int qurrry(int rt, int l, int r, int L, int R) {
    if (L <= l && r <= R) {
        return last[rt];
    }
    push_down(rt, l, r);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (L <= mid) {
        ans += qurrry(lson, L, R);
    }
    if (R > mid) {
        ans += qurrry(rson, L, R);
    }
    return ans;
}
int update(int rt, int l, int r, int L, int R,int f) {
    if (L <= l && r <= R) {
        int ans = r - l + 1 - last[rt];
        if (f==1) {
            last[rt] = r - l + 1;
            tag[rt] =1 ;
        }
        else {
            last[rt] = 0;
            tag[rt] = 0;
        }
        return ans;
    }
    push_down(rt, l, r);
    int mid = (l + r) >> 1;
    int ans = 0;
    if (L <= mid) {
        ans += update(lson, L, R,f);
    }
    if (R > mid) {
        ans += update(rson, L, R,f);
    }
    push_up(rt);
    return ans;
}
int bin_serch(int x, int num) {//二分查找从x位置开始第num个空位的位置
    int l = x, r = n,ans=0;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (qurrry(1, 1, n, x, mid) >= num) {
            ans = mid;//x-mid中是满足num个数的,更新ans
            r = mid - 1;
        }
        else {
            l = mid + 1;
        }
    }
    return ans;
}
int main() {
    //freopen("test.txt", "r", stdin);
    int t; scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        build(1, 1, n);
        int cmd, a, b;
        while (m--) {
            scanf("%d", &cmd);
            if (cmd == 1) {
                int a, k; scanf("%d%d", &a, &k);
                a++;
                int cnt = qurrry(1, 1, n, a, n);
                if (cnt==0) {
                    printf("Can not put any one.\n"); continue;
                }
                int lpos = bin_serch(a, 1);
                int rpos = bin_serch(a, min(cnt, k));
                update(1, 1, n, lpos, rpos, 0);
                printf("%d %d\n", lpos-1, rpos-1);
            }
            else {
                int a, b; scanf("%d%d", &a, &b);
                printf("%d\n", update(1, 1, n, a+1, b+1, 1));
            }
        }
        printf("\n");
    }
    return 0;
}

 

思路:
posted @ 2021-03-27 16:08  cono奇犽哒  阅读(66)  评论(0)    收藏  举报