题意:有n个房间,每个房间有若干个灯泡需要更换,如果还有灯泡没被换掉,那么主人公每个月月初会购买m个灯泡,然后从房间1到n检查,如果手上的新灯泡数可以把这个房间的灯泡全部换掉,那么就全换,否则就跳过这个房间。
有q个询问,问第i个月月末的时候有多少房间被更新完毕,手上还有多少灯泡。
思路:线段树维护最小值,每次查询小于目前灯泡数的最左边的那个房间,然后就是模拟了。。。
#include<iostream>
#include<stdio.h>
#include<string>
#include<queue>
#include<stack>
#include<string.h>
#include<algorithm>
#define lson l,mid,rt << 1
#define rson mid + 1,r,rt << 1|1
typedef long long int ll;
using namespace std;
const int maxn = 1e5 + 10;
const int inf = 0x3f3f3f3f;
int bit[maxn << 2],n,room[maxn];
int a[maxn],ans[maxn][2];
void push_up(int rt)
{
bit[rt] = min(bit[rt << 1] , bit[rt << 1|1]);
}
void build(int l,int r,int rt)
{
if(l == r)
{
scanf("%d",&bit[rt]);
room[l] = bit[rt];
}
else
{
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
int mid = (r + l) >> 1;
if(L <= l && R >= r)
{
bit[rt] = c;
return ;
}
else
{
if(L <= mid)
{
update(L,R,c,lson);
}
if(R > mid)
{
update(L,R,c,rson);
}
push_up(rt);
}
}
int query(int c,int l,int r,int rt)
{
int mid = (l + r) >> 1;
if(bit[rt] > c)
{
return -1;
}
if(l == r)
{
return l;
}
else
{
if(bit[rt << 1] <= c)
{
return query(c,lson);
}
else
{
return query(c,rson);
}
}
}
int main()
{
int i,j,m,q,mx;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(bit,inf,sizeof(bit));
build(1,n,1);
scanf("%d",&q);
mx = 0;
for(i = 1;i <= q;i++)
{
scanf("%d",&a[i]);
mx = max(mx,a[i]);
}
int temp = m,p,num = 0;;
for(i = 1;i <= mx;i++)
{
p = query(temp,1,n,1);
if(p == -1)
{
ans[i][0] = num;
ans[i][1] = temp;
temp += m;
}
else
{
while(p != -1)
{
num++;
temp -= room[p];
room[p] = inf;
update(p,p,inf,1,n,1);
p = query(temp,1,n,1);
}
ans[i][0] = num;
ans[i][1] = temp;
temp += m;
if(num == n)
temp -= m;
}
}
for(i = 1;i <= q;i++)
{
printf("%d %d\n",ans[a[i]][0],ans[a[i]][1]);
}
}
return 0;
}