https://nanti.jisuanke.com/t/30996
题意:n个房间,每个房间有ai盏旧灯,每个月可以买m盏新灯,要求:按房间顺序换灯,如果剩下的新灯数目大于ai,那么进行更换,否则跳过该房间,判断下一个房间。如果所有房间都换完灯,那么久不会再买新灯。
q次询问,每次询问该月已换的房间数以及剩余的新灯数量。
题解:朴素线段树维护最小值,最小值指区间内房间的最小旧灯数。每次查询如果当前剩余的新灯大于某一区间的最小值,那么进行替换,更新剩余新灯。(注意查询顺序要从左往右。)最后一通乱搞
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#include<vector>
using namespace std;
#define inf 0x3f3f3f
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,a,n) for(int i=n;i>=a;i--)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define mem(a,b) memset(a,b,sizeof(a));
#define lowbit(x) x&-x;
typedef long long ll;
const int maxn = 1e5+5;
int n,m;
int lamp[maxn << 2];
int q;
int month[maxn];
int re;
int MIN[maxn << 2];
int ans1[maxn], ans2[maxn];
void pushup(int rt){
MIN[rt] = min(MIN[rt<<1],MIN[rt<<1|1]);
}
void build(int l,int r,int rt){
if(l == r){
scanf("%d",&MIN[rt]);
return ;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
pushup(rt);
}
int query(int l,int r,int rt,int val){
if(l == r){
re -= MIN[rt];
MIN[rt] = inf;
return 1; //查询到
}
int mid = (l + r) >> 1;
int pos = 0;
if(MIN[rt<<1] <= val){ //左子树找到比val小的
pos = query(lson,val);
pushup(rt);
return pos;
}
if(MIN[rt<<1|1] <= val){ //右子树找到比val小的
pos = query(rson,val);
pushup(rt);
return pos;
}
return 0;
}
int main(){
while(~scanf("%d%d",&n,&m)){
build(1,n,1);
scanf("%d",&q);
int Maxmonth = 0;
for(int i=1; i<=q; i++){
scanf("%d",&month[i]);
Maxmonth = max(Maxmonth,month[i]);
}
int cur = 1;
int mark = 0; //表示换了多少个房间
int flag = 0; //是否换完
while(cur <= Maxmonth){
if(!flag) re += m;
while(query(1,n,1,re)&&!flag){
mark++;
}
if(!flag){
ans1[cur] = mark;
ans2[cur] = re;
}else{
ans1[cur] = n;
ans2[cur] = re;
}
cur++;
if(mark >= n){ //换完了
flag = 1 ;
}
}
for(int i = 1; i <= q; i++)
printf("%d %d\n",ans1[month[i]],ans2[month[i]]);
}
}