题目太长不贴。
题目大意:每个月买入m盏节能灯,从头检查n个房间,如果手头的节能灯可以把当前房间的老灯全换掉,就全换掉,否则存着,等够了再换。q个查询,给出月份,问该月换完了多少个房间,换了之后剩下几盏节能灯。
典型教训题,如此简单如此裸的一道线段树我们好几个人看了半天居然没一个人反应过来……
我决定这周四的网络赛先把题全看一遍再说……
不需要把答案push到树顶,只要维护“整个区间内有没有能替换的房间”,也就是最小值,然后再去寻找答案,优先走编号小的房间(也就是左子树)就行了……
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
const int maxq = 1e5 + 5;
int t[maxn << 2], tar;
void pushUp(int i) {
t[i] = min(t[i << 1], t[i << 1 | 1]);
}
void build(int i, int l, int r) {
if(l == r) {
scanf("%d", &t[i]);
return;
}
int mid = (l + r) / 2;
build(i << 1, l, mid);
build(i << 1 | 1, mid + 1, r);
pushUp(i);
}
void query(int i, int l, int r, int lpl) {
if(l == r) {
tar = t[i];
t[i] = 3e5;
return;
}
int mid = (l + r) / 2;
if(t[i << 1] <= lpl) {
query(i << 1, l, mid, lpl);
} else {
query(i << 1 | 1, mid + 1, r, lpl);
}
pushUp(i);
}
int main() {
int n, m, q, d[maxq];
int ans[maxn], ans2[maxn];
scanf("%d%d", &n, &m);
build(1, 1, n);
scanf("%d", &q);
int maxx = -1;
for(int i = 0; i < q; i++) {
scanf("%d", &d[i]);
maxx = max(maxx, d[i]);
}
int cnt = 0, lpl = 0;
for(int i = 1; i <= maxx; i++) {
if(cnt < n) {
lpl += m;
}
// printf("%d\n",t[1]);
while(t[1] <= lpl) {
query(1, 1, n, lpl);
// printf("%d %d\n", tar, i);
lpl -= tar;
cnt++;
}
ans[i] = cnt;
ans2[i] = lpl;
}
for(int i = 0; i < q; i++) {
printf("%d %d\n", ans[d[i]], ans2[d[i]]);
}
return 0;
}