https://nanti.jisuanke.com/t/30996
题意:
有n个房间,里面分别有ai盏灯需要更换,Lpl每月都会买m盏灯,如果刚好能更换一个房间就会把灯都更换掉,如果不能就会继续找下一个房间看是否能全部更换,剩余的灯就会被留到下个月使用,最后输出她每月最多能更换的房间数和所剩余的灯的数量。
思路:
直接线段树找到最左边小于一个数的位置,然后把可以换的更新成inf。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
const int inf=0x7fffffff;
int minn[maxn<<2];
int x[maxn],y[maxn];
int a[maxn];
int w[maxn];
void update(int pos,int val,int l,int r,int rt)
{
if(l==r)
{
minn[rt]=val;
return;
}
int mid=(l+r)/2;
if(pos<=mid)update(pos,val,l,mid,rt*2);
else update(pos,val,mid+1,r,rt*2+1);
minn[rt]=min(minn[rt*2],minn[rt*2+1]);
}
int query(int val,int l,int r,int rt)
{
if(l==r)return l;
int mid=(l+r)/2;
if(minn[rt*2]<=val)return query(val,l,mid,rt*2);
if(minn[rt*2+1]<=val)return query(val,mid+1,r,rt*2+1);
return -1;
}
int main()
{
int m,n;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&w[i]),update(i,w[i],1,n,1);
int q;
scanf("%d",&q);
int mx=0;
for(int i=1;i<=q;i++)
scanf("%d",&a[i]),mx=max(a[i],mx);
int ans=0;
int js=0;
for(int i=1;i<=mx;i++)
{
ans+=m;
while(1)
{
int id=query(ans,1,n,1);
if(id!=-1)
{
js++;
ans-=w[id];
update(id,inf,1,n,1);
x[i]=js;
y[i]=ans;
}
else
{
x[i]=js;
y[i]=ans;
break;
}
}
}
for(int i = 1;i <= q;i++)
printf("%d %d\n",x[a[i]],y[a[i]]);
}