1. 程式人生 > 實用技巧 >CF994B Knights of a Polygonal Table

CF994B Knights of a Polygonal Table

CF994B Knights of a Polygonal Table

洛谷傳送門

題目描述

有 nnn 個騎士想決戰。每個騎士都有能力值,且身上帶有一些金幣。如果騎士 AAA 的能力值大於騎士 BBB ,那麼騎士 AAA 就可以殺死騎士 BBB ,並獲得騎士 BBB 身上的所有金幣。但就算是騎士也不會殘忍過度,他們最多隻會殺死 kkk 個騎士。對於每一位騎士,請你求出在決戰後他身上金幣的最大值。

輸入格式

第 111 行,有 222 個整數,分別為騎士人數 nnn 和殺人數上限 kkk 。

(資料範圍: 1⩽n⩽1051 \leqslant n \leqslant 10^{5}1⩽n⩽105 , 0⩽k⩽min(n−1, 10)0 \leqslant k \leqslant min(n - 1,\ 10)0⩽k⩽min(n−1, 10) )

第 222 行,有 nnn 個整數,表示每個騎士的能力值 pip_ipi 。

第 333 行,有 nnn 個整數,表示每個騎士原有的金幣 cic_ici 。

(資料範圍: 1⩽pi⩽1091 \leqslant p_i \leqslant 10^{9}1⩽pi⩽109 , 0⩽ci⩽1090 \leqslant c_i \leqslant 10^{9}0⩽ci⩽109 )

##輸出格式

111 行內輸出 nnn 個整數,決戰後每個騎士身上金幣的最大值,每兩個數間以單個空格隔開。

##提示與說明

  • 第 111 組樣例的解釋:

第 111 個騎士是最蒻的,因此他誰也不能殺,只能保留自己原有的金幣。

第 222 個騎士只能殺死第 111 個騎士,因此他最多擁有 2+1=32 + 1 = 32+1=3 個金幣。

第 333 個騎士是最蔃的,但他只能選擇殺 k=2k = 2k=2 個騎士。顯然他會殺死第 222 個騎士和 第 444 個騎士,因為他們身上的金幣更多。因此他最多擁有 11+2+33=4611 + 2 + 33 = 4611+2+33=46 個金幣。

第 444 個騎士應該殺死第 111 個和第 222 個騎士,因此他最多擁有 33+1+2=3633 + 1 + 2 = 3633+1+2=36 個金幣。

  • 第 222 組樣例的解釋:

除了最蒻的第 111 個騎士誰也不能殺,其他騎士都能殺死前一個騎士並獲得他的金幣。

  • 第 333 組樣例的解釋:

由於只有一個騎士在決戰中,他無法殺死任何人。

感謝@Sooke 提供翻譯


題解:

感覺這些綠題都比上面的黃題簡單呢...

很容易想的貪心策略:在所有自己能吃的騎士裡,儘可能吃金幣多的。(採用了CSP2020貪吃蛇的說法(滑稽))

貪心策略這麼好想,我覺得應該是卡時間的,也就是卡依題意模擬。

後來發現根本不卡直接模擬的做法。不需要套什麼平衡樹,有病麼?

直接按武力值大小排序,然後從頭到尾維護一個大根堆來維護金幣數量,再加一個編號的對映,就OK了啊。

時間複雜度級別在\(O(n\log n)\)。完全可以通過本題。

於是開始思考有沒有\(O(n)\)做法,但是沒想出來...(太菜了)

如果各路大神能想到這道題的資料加強版,請一定要聯絡我哦!我們交流一下思路。

程式碼:

#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
#define int long long
using namespace std;
const int maxn=1e5+5;
int n,k;
struct node
{
    int p,c,ans,id;
}a[maxn];
priority_queue<int> q;
vector<int> v;
bool cmp(node a,node b)
{
    return a.p<b.p;
}
bool cmp1(node a,node b)
{
    return a.id<b.id;
}
signed main()
{
    scanf("%lld%lld",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i].p);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i].c);
        a[i].ans=a[i].c;
        a[i].id=i;
    }
    sort(a+1,a+n+1,cmp);
    q.push(a[1].c);
    for(int i=2;i<=n;i++)
    {
        int s=q.size();
        int t=min(k,s);
        for(int j=1;j<=t;j++)
        {
            int x=q.top();
            q.pop();
            v.push_back(x);
        }
        for(int j=0;j<v.size();j++)
        {
            a[i].ans+=v[j];
            q.push(v[j]);
        }
        v.clear();
        q.push(a[i].c);
    }
    sort(a+1,a+n+1,cmp1);
    for(int i=1;i<=n;i++)
        printf("%lld ",a[i].ans);
    return 0;
}