线段树求区间第一个不大于val的值Lpl and Energy-saving Lamps
Posted stolf
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树求区间第一个不大于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]]);
}
}
以上是关于线段树求区间第一个不大于val的值Lpl and Energy-saving Lamps的主要内容,如果未能解决你的问题,请参考以下文章
ACM-ICPC 2018 南京赛区网络预赛 G. Lpl and Energy-saving Lamps (弱线段树)
计蒜客 Lpl and Energy-saving Lamps(二分+线段树区间最小)