hdu 4614(区间更新)

这里写代码片题意:有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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-25 02:15:37

hdu 4614(区间更新)的相关文章

HDU 1698 区间更新

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 20532    Accepted Submission(s): 10284 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing

【HDU 4614】Vases and Flowers(线段树区间更新懒惰标记)

题目0到n-1的花瓶,操作1在下标a开始插b朵花,输出始末下标.操作2清空[a,b]的花瓶,求清除的花的数量.线段树懒惰标记来更新区间.操作1,先查询0到a-1有num个空瓶子,然后用线段树的性质,或者二分找出第num+1个空瓶子的下标,和第num+b个空瓶子的下标.再区间更新为满.操作2,也相当于区间更新为空. #include<cstdio> #include<cstring> #include<algorithm> #define N 50001 using na

HDU 4614 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 a

hdu 4970 树状数组区间更新 思维题

http://acm.hdu.edu.cn/showproblem.php?pid=4970 好像还没有用树状数组写过区间更新,但是树状数组的确比线段树快很多,不知道跟ZKW线段树比效率怎么样: 先贴个模板: #include <cstdio> const int MAXN = 1024; int B[MAXN], C[MAXN]; #define LOWBIT(x) ((x)&(-(x))) void bit_update(int *a, int p, int d) { for (

HDU 1556 Color the ball(线段树:区间更新)

http://acm.hdu.edu.cn/showproblem.php?pid=1556 题意: N个气球,每次[a,b]之间的气球涂一次色,统计每个气球涂色的次数. 思路: 这道题目用树状数组和线段树都可以,拿这道题来入门一下线段树的区间更新. 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 6 const int maxn = 1000

HDU 1398:Just a Hook(线段树区间更新)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 Just a Hook Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

HDU 3397 Sequence operation(区间合并 + 区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给定n个数,由0,1构成.共有5种操作.每个操作输入3个数,op,a,b. op == 0,将区间[a,b]赋值为0: op == 1,将区间[a,b]赋值为1: op == 2,将区间[a,b]内的01反转: op == 3,查询区间[a,b]中1的个数: op == 4,查询区间[a,b]中连续1的最大长度: 思路:区间合并 + 区间更新.每个结点存7个数: 区间内1的个数c1. 从