BZOJ 3735 Pa2013Konduktorzy

Problem

BZOJ

Solution

先喷一下这道题的提示,能继续检票的条件可以无视。

我们希望能减少中途对最后答案无意义的模拟,那么考虑二分最后的位置,然后用堆模拟最后几步。
s t e p = i = 1 k p o s a [ i ]
那么二分出这个pos之后,就可以再向前推几步,然后用堆模拟即可。

本题稍微有点卡常,手写一个数据结构比pair快。注意check的时候一定要中途就判断tmp是否小于0,最后检查可能导致爆longlong,然后不停WA。

Code

#include <functional>
#include <algorithm>
#include <cstdio>
#define rg register
#define mk(x,y) (data){x,y}
using namespace std;
typedef long long ll;
typedef pair<ll,int> pii;
const int maxn=100010;
const ll INF=1e18;
template <typename Tp> inline void getmin(Tp &x,Tp y){if(y<x) x=y;}
template <typename Tp> inline void getmax(Tp &x,Tp y){if(y>x) x=y;}
template <typename Tp> inline void read(Tp &x)
{
    x=0;int f=0;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    if(ch=='-') f=1,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    if(f) x=-x;
}
struct data{
    ll x;int y;
    bool operator < (const data &t)const
    {
        if(x==t.x) return y>t.y;
        return x>t.x;
    }
};
struct Heap{
    int p;data a[maxn];
    void push(data x){a[++p]=x;push_heap(a+1,a+p+1);}
    void pop(){pop_heap(a+1,a+p+1);p--;}
}h;
ll n,l=1,r=INF,m,pos,now,fr,ans[maxn];
int k,se,a[maxn];
int check(ll t)
{
    ll tmp=n;
    for(rg int i=1;tmp>=0&&i<=k;i++)
      tmp-=t/a[i];
    if(tmp>=0) return 1;
    return 0;
}
int main()
{
    read(n);read(k);
    for(rg int i=1;i<=k;i++) read(a[i]);
    while(l<=r)
    {
        m=(l+r)>>1;
        if(check(m)) pos=m,l=m+1;
        else r=m-1;
    }
    m=pos;
    for(rg int i=1;i<=k;i++) getmin(pos,max((m/a[i]-1)*a[i],0ll));
    for(rg int i=1;i<=k;i++) now+=pos/a[i],h.push(mk(pos/a[i]*a[i],i));
    while(now<n)
    {
        fr=h.a[1].x;se=h.a[1].y;
        ans[se]=++now;h.pop();h.push(mk(fr+a[se],se));
    }
    for(rg int i=1;i<=k;i++) printf("%lld ",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/as_a_kid/article/details/81054888
今日推荐