【线段树求区间第一个不大于val的值】Lpl and Energy-saving Lamps

https://nanti.jisuanke.com/t/30996

线段树维护区间最小值,查询的时候优先向左走,如果左边已经找到了,就不用再往右了。

一个房间装满则把权值标记为INF,模拟一遍,注意考虑一个月内装满多个房间装满所有房间后不用再购买的情况。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
const int maxn = 100005;
const int INF = 0x3f3f3f3f;
using namespace std;
int a[maxn], St[maxn << 2], Q[maxn], ans[maxn], remain[maxn];
void PushUp(int rt) {
    St[rt] = min(St[rt << 1], St[rt << 1 | 1]);
}
void Build(int l, int r, int rt) {
    if (l == r) {
        St[rt] = a[l];
        return;
    }
    int m = (l + r) >> 1;
    Build(l, m, rt << 1);
    Build(m + 1, r, rt << 1 | 1);
    PushUp(rt);
}
void Update(int L, int C, int l, int r, int rt) {
    if (l == r) {
        St[rt] = C;
        return;
    }
    int m = (l + r) >> 1;
    if (L <= m) {
        Update(L, C, l, m, rt << 1);
    }
    else {
        Update(L, C, m + 1, r, rt << 1 | 1);
    }
    PushUp(rt);
}
int Query(int val, int L, int R, int l, int r, int rt) {
    if (l == r) {
        if (St[rt] <= val) {
            return l;
        }
        return INF;
    }
    if (L <= l && R >= r) {
        if (St[rt] > val) {
            return INF;
        }
    }
    int m = (l + r) >> 1;
    int ANS = INF;
    if (L <= m) ANS = min(ANS, Query(val, L, R, l, m, rt << 1));
    if (ANS != INF) {
        return ANS;
    }
    if (R > m) ANS = min(ANS, Query(val, L, R, m + 1, r, rt << 1 | 1));
    return ANS;
}
int main() {
    int n, m, q, mxq = 0;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    scanf("%d", &q);
    for (int i = 1; i <= q; i++) {
        scanf("%d", &Q[i]);
        mxq = max(mxq, Q[i]);
    }
    Build(1, n, 1);
    for (int i = 1, now = m, fin = 0; i <= mxq; i++, fin >= n ? 0 : now += m) {
        int p = Query(now, 1, n, 1, n, 1);
        ans[i] = ans[i - 1];
        while (p != INF) {
            fin++;
            ans[i]++;
            now -= a[p];
            Update(p, INF, 1, n, 1);
            p = Query(now, 1, n, 1, n, 1);
        }
        remain[i] = now;
    }
    for (int i = 1; i <= q; i++) {
        printf("%d %d\n", ans[Q[i]], remain[Q[i]]);
    }
}

原文地址:https://www.cnblogs.com/stolf/p/9572833.html

时间: 2024-10-03 14:38:00

【线段树求区间第一个不大于val的值】Lpl and Energy-saving Lamps的相关文章

2016年湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

原题链接 http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1809 Description Bobo has a balanced parenthesis sequence P=p1 p2…pn of length n and q questions. The i-th question is whether P remains balanced after pai and pbi  swapped. Note that questions ar

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (

HDU6447 YJJ&#39;s Salesman-2018CCPC网络赛-线段树求区间最值+离散化+dp

目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog Problem:Portal传送门 ?原题目描述在最下面. ?1e5个点,问从(0,0)走到(1e9,1e9)的最大收益. ?当你从(u-1,v-1)走到(u,v)时,你可以获得点(u,v)的权值. Solution: ?十分详细了. ?直接线段树区间最值.当然也可以树状数组,不能st表. ?\(dp[i] = max(query\_max(0,dp[i]-1,1)+val[i] ,

LightOJ Array Queries 1082【线段树求区间最值】

1082 - Array Queries PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 64 MB Given an array with N elements, indexed from 1 to N. Now you will be given some queries in the form I J, your task is to find the minimum value from index

hdu1166 敌兵布阵(线段树 求区间和 更新点)

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 59427    Accepted Submission(s): 25098 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又開始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务

poj 3264 线段树 求区间最大最小值

Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer John decides to organize a game of Ultimate Frisbee with some of the cows. To keep things simple, he will take a contiguous rang

nyoj1185 最大最小值 (线段树求区间最大值和最小值)

对于不懂线段树的,先看为这篇文章理解下.点击打开链接 这道题普通方法 ,TLE. 最大最小值 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 给出N个整数,执行M次询问. 对于每次询问,首先输入三个整数C.L.R: 如果C等于1,输出第L个数到第R个数之间的最小值: 如果C等于2,输出第L个数到第R个数之间的最大值: 如果C等于3,输出第L个数到第R个数之间的最小值与最大值的和. (包括第L个数和第R个数). 输入 首先输入一个整数T(T≤100),表示有T组数据.

Just a Hook-HDU1698(线段树求区间)

http://acm.hdu.edu.cn/showproblem.php?pid=1698 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 the same len

线段树 求区间连乘——hdu 3074 Multiply game

Multiply game Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2189    Accepted Submission(s): 783 Problem Description Tired of playing computer games, alpc23 is planning to play a game on number