(南京区域资格赛) G Lpl and Energy-saving Lamps(线段树)

本文介绍了一个有趣的节能改造问题:主人公Lpl在一座拥有众多房间的城堡中更换旧灯泡为节能灯。通过使用线段树数据结构,实现了高效查找并更新房间状态的功能,以确保每月城堡内的节能灯替换进度及剩余数量的准确记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

During tea-drinking, princess, amongst other things, asked why has such a good-natured and cute Dragon imprisoned Lpl in the Castle? Dragon smiled enigmatically and answered that it is a big secret. After a pause, Dragon added:

— We have a contract. A rental agreement. He always works all day long. He likes silence. Besides that, there are many more advantages of living here in the Castle. Say, it is easy to justify a missed call: a phone ring can’t reach the other side of the Castle from where the phone has been left. So, the imprisonment is just a tale. Actually, he thinks about everything. He is smart. For instance, he started replacing incandescent lamps with energy-saving lamps in the whole Castle…

Lpl chose a model of energy-saving lamps and started the replacement as described below. He numbered all rooms in the Castle and counted how many lamps in each room he needs to replace.

At the beginning of each month, Lpl buys mmm energy-saving lamps and replaces lamps in rooms according to his list. He starts from the first room in his list. If the lamps in this room are not replaced yet and Lpl has enough energy-saving lamps to replace all lamps, then he replaces all ones and takes the room out from the list. Otherwise, he’ll just skip it and check the next room in his list. This process repeats until he has no energy-saving lamps or he has checked all rooms in his list. If he still has some energy-saving lamps after he has checked all rooms in his list, he’ll save the rest of energy-saving lamps for the next month.

As soon as all the work is done, he ceases buying new lamps. They are very high quality and have a very long-life cycle.

Your task is for a given number of month and descriptions of rooms to compute in how many rooms the old lamps will be replaced with energy-saving ones and how many energy-saving lamps will remain by the end of each month.
Input

Each input will consist of a single test case.

The first line contains integers nnn and m(1≤n≤100000,1≤m≤100)m (1 \le n \le 100000, 1 \le m \le 100)m(1≤n≤100000,1≤m≤100) — the number of rooms in the Castle and the number of energy-saving lamps, which Lpl buys monthly.

The second line contains nnn integers k1,k2,…,knk_1, k_2, …, k_nk1​,k2​,…,kn​
(1≤kj≤10000,j=1,2,…,n)(1 \le k_j \le 10000, j = 1, 2, …, n)(1≤kj​≤10000,j=1,2,…,n) — the number of lamps in the rooms of the Castle. The number in position jjj is the number of lamps in jjj-th room. Room numbers are given in accordance with Lpl’s list.

The third line contains one integer q(1≤q≤100000)q (1 \le q \le 100000)q(1≤q≤100000) — the number of queries.

The fourth line contains qqq integers d1,d2,…,dqd_1, d_2, …, d_qd1​,d2​,…,dq​
(1≤dp≤100000,p=1,2,…,q)(1 \le d_p \le 100000, p = 1, 2, …, q)(1≤dp​≤100000,p=1,2,…,q) — numbers of months, in which queries are formed.

Months are numbered starting with 111; at the beginning of the first month Lpl buys the first m energy-saving lamps.
Output

Print qqq lines.

Line ppp contains two integers — the number of rooms, in which all old lamps are replaced already, and the number of remaining energy-saving lamps by the end of dpd_pdp​ month.
Hint

Explanation for the sample:

In the first month, he bought 444 energy-saving lamps and he replaced the first room in his list and remove it. And then he had 111 energy-saving lamps and skipped all rooms next. So, the answer for the first month is 1,1−−−−−−11,1——11,1−−−−−−1 room’s lamps were replaced already, 111 energy-saving lamp remain.
样例输入

5 4
3 10 5 2 7
10
5 1 4 8 7 2 3 6 4 7

样例输出

4 0
1 1
3 6
5 1
5 1
2 0
3 2
4 4
3 6
5 1

思路:我们可以直接用线段树求出区间最左边小于某个数的数,线段树存1-n房间的灯数,维护区间最小值,查询的时候优先向左走就好了,

一个房间满了我们就用线段树将这个房间的值更新为inf,然后模拟下就好了。这样操作次数最多不大于1e5次,复杂度为 O(nlog(n))。

这道题算是一道非常基础的线段树,没什么复杂的操作,注意一次更新可能会有多个房间被填满,加个while处理下就好了。

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int inf = 1e9;
const int M = 2e5+10;
int sum[M<<2],n,k,q;
int a[M],b[M],x[M],y[M];

void update(int p,int c,int l,int r,int rt)
{
     if(l == r && l == p){
        sum[rt] = c;
        return ;
     }
     int m = (l + r) >> 1;
     if(p <= m) update(p,c,lson);
     else update(p,c,rson);
     sum[rt] = min(sum[rt<<1],sum[rt<<1|1]);
}

int query(int p,int l,int r,int rt)
{
    if(l == r) return l;
    int m = (l + r) >> 1;
    if(sum[rt<<1] <= p) return query(p,lson);
    if(sum[rt<<1|1] <= p) return query(p,rson);
    return -1;
}

int main()
{
    scanf("%d%d",&n,&k);
    for(int i = 1;i <= n;i ++){
        scanf("%id", &a[i]);
        update(i,a[i],1,n,1);
    }
    scanf("%d",&q);
    int mx = 0;
    for(int i = 1;i <= q;i++){
        scanf("%d",&b[i]);
        mx = max(b[i],mx);
    }
    int ans = 0, cnt = 0;
    for(int i = 1;i <= mx;i++){
        ans += k;
        while(1){   //一次更新可能有多个房间被填满
            int num = query(ans, 1, n, 1);
            if(num != -1) {
                cnt++, ans -= a[num];
                update(num, inf, 1, n, 1);
                x[i] = cnt, y[i] = ans;
            }
            else {
                x[i] = cnt, y[i] = ans;
                break;
            }
        }

    }
    for(int i = 1;i <= q;i++)
        printf("%d %d\n",x[b[i]],y[b[i]]);

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值