ICPC网络赛 - Lpl and Energy-saving Lamps (线段树)

Lpl and Energy-saving Lamps

题目链接: Lpl and Energy-saving Lamps

题意

你有N个房间(N<1e5),每天买M个灯泡(M<100),每个房间都有需要装的灯泡数,每天装灯泡时,必须从第一个房间到最后一个房间,如果可以装,即手中的灯泡数大于房间需要的灯泡数,就装。总共有Q个询问(Q<1e5),每次询问的天数,小于等于1e4,每次询问输出当前天时,所点亮的房间数和现在手中的灯泡数。


思路

将题目简化,我们即可知道,我们所需要知道的是,当前序列中第一个小于等于手中剩下灯泡的房间数。那么我们用线段树即可,维护最小值,每次优先访问左节点,如果左节点中最小的值小于现在手中的灯泡数时,进行操作,暴力模拟。


代码

#include <bits/stdc++.h>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const int MAXN = (int)1e5+7;
const int INF = (int)0x3f3f3f3f;

#define lson rt<<1
#define rson rt<<1|1

inline int read() { int c = 0, f = 1;char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1;ch = getchar();}
    while (ch >= '0' && ch <= '9') {c = c * 10 + ch - '0';ch = getchar();}
    return c * f;
}

int A[MAXN];

int sum[MAXN<<2];

void PushUp(int rt){sum[rt] = min(sum[lson] , sum[rson]); }

void Build(int l,int r,int rt){
    if (l == r){
        sum[rt] = A[l];
        return ;
    }
    int m = (l+r)>>1;
    Build(l,m,lson);
    Build(m+1,r,rson);
    PushUp(rt);
}

void Update(int L,int C,int l,int r,int rt){
    if (l == r){
        sum[rt] = C;
        return ;
    }
    int m = (l+r)>>1;
    if (L <= m) Update(L,C,l,m,lson);
    else        Update(L,C,m+1,r,rson);
    PushUp(rt);
}

int Query(int l,int r,int rt,int val){
    if (l == r) {
        return l;
    }
    int m = (l+r)>>1;
    int ans = INF;
    if (sum[lson] <= val) {ans = Query(l,m,lson,val); }
    else if (sum[rson] <= val) {ans = Query(m+1,r,rson,val); }
    return ans;
}

int room[MAXN];
int rem[MAXN];

int main()
{
    int N,M;
    N = read(),M = read();
    rep(i,1,N) A[i] = read();
    Build(1,N,1);

    int re = 0;
    rep(i,1,100000){
        re += M;
        if (sum[1] == INF) re -= M;
        room[i] = room[i-1];
        rem[i] = re;
        while (sum[1] <= re) {
            int id = Query(1,N,1,re);
            re -= A[id];
            room[i] ++;
            rem[i] -= A[id];
            Update(id,INF,1,N,1);
        }
    }

    int Q = read();
    while (Q --) {
        int d = read();
        printf("%d %d\n",room[d],rem[d]);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值