hdu 4614 Vases and Flowers

题目大意:有编号为[0,N-1]的花盆,有下述2种操作:

1 A F,有F朵花,从A开始放入花盆,(最后放不下的丢弃)

2 A B,清理[A,B]花盆里的花。

对每种操作:对1输出第一个和最后一个放入花的花盆编号,无位置时输出“Can not put any one.”

对2输出清理掉的花盆数量。

对2操作,就是一个简单的线段树区间和的查询,不提先。

对于1操作,相当要找到[A, N-1]花盆中第k个空盆。一开始想的时候,线段树结点T[rt]表示的是这个区间花的数量,这样来求第k个空盆比较麻烦,后面转成想:T[rt]表示的是这个区间空盆数量,再找的时候就如同query2写的,非常流畅了。另:第k个空盆,这个k得在剩余空盆和实际要插的花朵数量之间取min。

#include <stdio.h>
#include <iostream>
#include <string.h>
using namespace std;

#define ll long long
#define FOR(i,a,b) for(int i=(a);i<=(b);++i)
#define DOR(i,a,b) for(int i=(a);i>=(b);--i)

const int maxN=5e4+5,inf=0x3f3f3f3f;
int N, M, K, T[maxN<<2], Z[maxN<<2];

#define lson l,m,rt*2
#define rson m+1,r,rt*2+1

void push_up(int rt) {T[rt] = T[rt * 2] + T[rt * 2 + 1];}
void push_down(int l, int r, int rt) {
    if (Z[rt] == -1) return;
    int lch = rt * 2, rch = lch + 1;
    Z[lch] = Z[rch] = Z[rt];
    int LE = r - l + 1;
    T[lch] = (LE - LE / 2) * Z[rt];
    T[rch] = (LE / 2) * Z[rt];
    Z[rt] = -1;
}
void build(int l, int r, int rt) {
    Z[rt] = -1;
    T[rt] = (r - l + 1);
    if (l == r) return;
    int m = (l + r) / 2;
    build(lson), build(rson);
    push_up(rt);
}
void update(int L, int R, int x, int l, int r, int rt) {
    if (L <= l && r <= R) {
        Z[rt] = x;
        T[rt] = (r - l + 1) * x;
        return;
    }
    push_down(l, r, rt);
    int m = (l + r) / 2;
    if (L <= m) update(L, R, x, lson);
    if (R > m) update(L, R, x, rson);
    push_up(rt);
}
int query1(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R) return T[rt];
    push_down(l, r, rt);
    int m = (l + r) / 2;
    int ans = 0;
    if (L <= m) ans += query1(L, R, lson);
    if (R > m) ans += query1(L, R, rson);
    // push_up(rt);
    return ans;
}
int query2(int L, int R, int k, int l, int r, int rt) {
    if (l == r) return l;
    push_down(l, r, rt);
    int m = (l + r) / 2;
    int cnt = query1(L, m, l, r, rt);
    if (cnt >= k) return query2(L, R, k, lson);
    else return query2(L, R, k - cnt, rson);
}

int main () {
    int cas;
    scanf("%d", &cas);
    FOR(ca, 1, cas) {
        scanf("%d%d", &N, &M);
        build(0, N - 1, 1);
        int op, a, b;
        FOR(j, 1, M) {
            scanf("%d%d%d", &op, &a, &b);
            if (op == 2) {
                int q = query1(a, b, 0, N - 1, 1);
                printf("%d\n", b - a + 1 - q);
                update(a, b, 1, 0, N - 1, 1);
            } else {
                if (query1(a, N - 1, 0, N - 1, 1) == 0) {
                    puts("Can not put any one.");
                    continue;
                }
                int empty = query1(a, N - 1, 0, N - 1, 1);
                int x = query2(a, N - 1, 1, 0, N - 1, 1);
                int y = query2(a, N - 1, min(b, empty), 0, N - 1, 1);
                printf("%d %d\n", x, y);
                update(x, y, 0, 0, N - 1, 1);
            }
        }
        puts("");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Rosebud/p/9689518.html