hdu 4614(区间更新)

来源:互联网 发布:安卓简单捕鱼源码 编辑:程序博客网 时间:2024/04/30 15:18

这里写代码片题意:有n个花瓶编号从0到n-1,初始花瓶都是空的,然后有两个操作,1 a b表示从位置a开始往后面找b(不够b个也可以)个空花瓶插花,输出插花的首位置和末位置,2 a b表示输出区间[a,b]有多少个花,并且把这个区间内所有花都拿走。
题解:很容易想到用线段树维护区间内有多少个空花瓶,然后操作2可以直接用普通的区间查询和区间修改,操作1可以看作先查询前a-1个花瓶有num个是空的,然后查询第num+1和第num+b个空花瓶的位置,这个查询也可以用线段树查询或二分查找来写。

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 50005;int n, q, tree[N << 2], flag[N << 2];void pushup(int k) {    tree[k] = tree[k * 2] + tree[k * 2 + 1];}void pushdown(int k, int left, int right) {    if (flag[k] == 1) {        flag[k * 2] = flag[k * 2 + 1] = flag[k];        tree[k * 2] = tree[k * 2 + 1] = 0;        flag[k] = 0;    }    else if (flag[k] == 2) {        int mid = (left + right) / 2;        flag[k * 2] = flag[k * 2 + 1] = flag[k];        tree[k * 2] = mid - left + 1;        tree[k * 2 + 1] = right - mid;        flag[k] = 0;    }}void build(int k, int left, int right) {    flag[k] = 0;    tree[k] = right - left + 1;    if (left != right) {        int mid = (left + right) / 2;        build(k * 2, left, mid);        build(k * 2 + 1, mid + 1, right);    }}void modify(int k, int left, int right, int l, int r, int x) {    if (l <= left && right <= r) {        flag[k] = x;        if (x == 1) tree[k] = 0;        else tree[k] = right - left + 1;        return;    }    pushdown(k, left, right);    int mid = (left + right) / 2;    if (l <= mid)        modify(k * 2, left, mid, l, r, x);    if (r > mid)        modify(k * 2 + 1, mid + 1, right, l, r, x);    pushup(k);}int query(int k, int left, int right, int l, int r) {    if (l <= left && right <= r)        return tree[k];    pushdown(k, left, right);    int mid = (left + right) / 2, res = 0;    if (l <= mid)        res += query(k * 2, left, mid, l, r);    if (r > mid)        res += query(k * 2 + 1, mid + 1, right, l, r);    pushup(k);    return res;}int Find(int k, int left, int right, int l, int r, int pos) {    if (left == right)        return left;    pushdown(k, left, right);    int mid = (left + right) / 2, temp;    if (r <= mid)        temp = Find(k * 2, left, mid, l, r, pos);    else if (l > mid)        temp = Find(k * 2 + 1, mid + 1, right, l, r, pos);    else {        if (pos <= tree[k * 2])            temp = Find(k * 2, left, mid, l, r, pos);        else            temp = Find(k * 2 + 1, mid + 1, right, l, r, pos - tree[k * 2]);    }    pushup(k);    return temp;}int main() {    int t;    scanf("%d", &t);    while (t--) {        scanf("%d%d", &n, &q);        build(1, 0, n - 1);        int op, l, x;        while (q--) {            scanf("%d%d%d", &op, &l, &x);            if (op == 1) {                int temp = query(1, 0, n - 1, l, n - 1);                if (!temp) {                    printf("Can not put any one.\n");                    continue;                }                else if (temp <= x)                    x = temp;                int num = 0;                if (l >= 1)                    num = query(1, 0, n - 1, 0, l - 1);                int st = Find(1, 0, n - 1, 0, n - 1, num + 1);                int en = Find(1, 0, n - 1, 0, n - 1, num + x);                printf("%d %d\n", st, en);                modify(1, 0, n - 1, st, en, 1);            } else {                printf("%d\n", x - l + 1 - query(1, 0, n - 1, l, x));                modify(1, 0, n - 1, l, x, 2);            }        }        printf("\n");    }    return 0;}
0 0
原创粉丝点击