ACM-ICPC 2018 南京赛区网络预赛 Lpl and Energy-saving Lamps (线段树:无序数组找到第一个小于val)

题意:n个房间,每个房间有ai盏旧灯,每个月可以买m盏新灯,要求:按房间顺序换灯,如果剩下的新灯数目大于ai,那么进行更换,否则跳过该房间,判断下一个房间。如果所有房间都换完灯,那么久不会再买新灯。

q次询问,每次询问该月已换的房间数以及剩余的新灯数量。

 

题解:线段树记录最小值,然后一遍模拟

#include<bits/stdc++.h>

using namespace std ;

#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define INF 0x3f3f3f3f
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) ///在左子树找到
    {
        pos = query(lson,val) ;
        pushup(rt);
        return pos;

    }
    if(MIN[rt<<1|1]<=val)///在右子树找到
    {
        pos = query(rson,val);
        pushup(rt);
        return pos;
    }
    return 0;
}
int main ( )
{
    int n,m;
    scanf("%d%d",&n,&m);
    build(1,n,1);
    int Maxmonth = 0;

    scanf("%d",&q);
    for(int i=1 ; i<=q ; i++)
    {
        scanf("%d",&month[i]);
        Maxmonth=max(month[i],Maxmonth);
    }
    int cur=1;
    int cnt=0;///换了多少
    int fa=0;///是否换完
    while(cur<=Maxmonth)
    {
        if(!fa)
        re+=m;
        while(query(1,n,1,re)&&!fa)
        cnt++;

        if(!fa)
        {
            ans1[cur]=cnt;
            ans2[cur]=re;
        }
        else
        {
            ans1[cur]=n;
            ans2[cur]=re;
        }
        cur++;
        if(cnt>=n)
        fa=1;
    }
    for(int i=1 ; i<=q ; i++)
    printf("%d %d\n",ans1[month[i]],ans2[month[i]]);

}
View Code

 

posted @ 2018-09-05 17:24  shuai_hui  阅读(102)  评论(0编辑  收藏  举报