多校day1-3 训练

钓鱼式的贪心(张老师的钓鱼真是万金油)
用堆维护还没走完的楼层

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long 
using namespace std;
int n,tot;
ll Time,m,ans,s; 
int h[1000005],v[1000005],w[1000005];
struct ty
{
    int v,h,id;
}heap[1000005];
void down(int id)
{
    while(id*2<=tot) 
    {
        int j;
        if(id*2+1>tot||heap[id*2+1].v<heap[id*2].v) j=id*2; else j=id*2+1;
        if(heap[id].v<heap[j].v) 
        {
            swap(heap[id],heap[j]);
            id=j;
        }
        else break;
    }
}
void up(int id)
{
    while(id/2>=1) 
    {
        if(heap[id].v>heap[id/2].v) 
        {
            swap(heap[id],heap[id/2]);
            id=id/2;
        }
        else break;
    }
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&h[i],&v[i]);
        s=s+v[i];
        w[i]=1;
        if(h[i]>1) 
        {
            tot++;
            heap[tot].v=v[i];
            heap[tot].h=h[i]-1;
            heap[tot].id=i; 
            up(tot);
        }
    }
    Time=m-(n-1);
    for(int i=n;i>=1;i--) 
    {
        if(i+1<=n) 
        {
            Time=Time+w[i+1]; //后面那幢楼已经去不了了,把花在那幢楼的时间加上 
            s=s-(ll)(w[i+1])*v[i+1]; //收益减去 
        }
        while(Time>0&&tot>0) 
        {
            while(tot>0&&heap[1].id>i) 
            {
                swap(heap[1],heap[tot]);
                tot--;
                down(1);
            }
            if(tot==0) break; 
            if(Time>=heap[1].h) 
            {
                Time-=heap[1].h; 
                w[heap[1].id]+=heap[1].h;
                s=s+(ll)(heap[1].v)*heap[1].h;
                swap(heap[1],heap[tot]);
                tot--;
                down(1); 
            }
            else
            {
                w[heap[1].id]+=Time;
                s=s+(ll)(heap[1].v)*(Time);
                heap[1].h-=Time; 
                Time=0; 
            }
        } 
        if(Time==0) ans=max(ans,s);
        if(Time>0&&tot==0) ans=max(ans,s);   
    }
    cout<<ans; 
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值