天天看點

hihocoder1269優化延遲

這道題其實隻是一道很裸的二分+優先隊列,然而本人比較笨,是以WA了好多次,下面附上代碼

#include <iostream>
#include <queue>
#include <string.h>
using namespace std;
priority_queue<long long>que;
int n,t=;
long long q;
int a[];
long long sum(int k)
{
    int b[];
    memset(b,,sizeof(b));
    long long sum2=;
    int i=,j=;
    while(i<=n)
    {
        if(que.size()<k)
        {
            que.push(a[i]);
            i++;
        }
        else
        {
            b[j++]=que.top();
            que.pop();
            que.push(a[i++]);
            //每次彈出一個數值後,一定要再壓入一個,否則的話,一個數會用到兩個i,會溢出
        }
    }
    while(!que.empty())
    {
        b[j++]=que.top();
        que.pop();
    }
    for(int i=; i<=n; i++)
        sum2+=i*b[i];
        //這裡用數組會比較友善一點,當然你每彈出一個乘一次也是可以的,但是可能會比較麻煩一點
    return sum2;
}

int main()
{
    while(cin>>n>>q)
    {
        for(int i=; i<=n; i++)
            cin>>a[i];
        int left=;
        int right=n;
//二分這塊的處理很重要,很多人覺得簡單,但是很容易寫錯

        while(left<=right)//一定要有等号
        {
            int mid=(left+right)/;
            if(sum(mid)<=q)//一定要有等号
            {
                t=min(mid,t);
                //之是以用二分是因為這道題随着k的增加,和逐漸減少,是遞減的,但又不是嚴格意義上的遞減有可能會出現相等的地方,是以這裡要用一下min
                right=mid-;
            }
            else
            {
                left=mid+;
            }
        }
        if(sum(t)<=q)
            cout<<t<<endl;
        else cout<<-<<endl;
//下面的這種也是可以的,但是我覺得并不是很好了解
        /*while(left<=right)
                {
                    int mid=(left+right)/2;
                    if(sum(mid)<=q)
                    {
                        right=mid-1;
                    }
                    else if(sum(mid)>q)
                    {
                        left=mid+1;
                    }
                }
        cout<<flag<<endl;
        if(sum(left)<=q)
        cout<<left<<endl;
        else cout<<-1<<endl;*/

    }
    return ;
}