Educational Codeforces Round 77 (Rated for Div. 2) E. Tournament(思維題)

題目

n(n<=2^18)個人進行兩兩比賽,勝者晉級下一輪,敗者淘汰

第i個人的實力值是i,對任意一輪,你都可以指定還沒淘汰的人如何配對比賽,用他們的實力值比大小,

特別地,對於第i個人,你的朋友可以用ai(1<=ai<=1e9)的代價去賄賂他,使其直接被淘汰

你的朋友也出現在這個序列中,用-1標記,

這樣log輪後就只剩一人,求你的朋友最後成爲冠軍所花費的最小代價

思路來源

卿學姐的B站講解

題解

考慮以下圖形,不難發現,

①無論如何指派,1都會在第一輪被淘汰, 23在第二輪,以此類推,

通過合理安排,第k輪可以存活的最小能力值的人是2^k,所以第k輪過後前(2^k)-1個人一定被淘汰

因此,要儘量讓小的值和朋友在靠前的輪比賽,

這樣朋友碰到的對手就是越來越強的,也說明了能不賄賂就不賄賂

②朋友如果是4,則最多隻需要賄賂1輪,即賄賂8,

最後一輪只能賄賂8,倒數第二輪可以賄賂[5,8],其實是①得出的結論,以此類推

③比自己能力值小的人,顯然不用賄賂

 

基於以上三點,倒序考慮輪次,

當遇到2的冪次的時候,再被迫賄賂代價最小的

代碼

#include<bits/stdc++.h>
using namespace std;
const int N=(1<<18)+5;
typedef long long ll;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
#define sci(a) scanf("%d",&(a))
int n,a[N];
bool ok[N];
priority_queue<int,vector<int>,greater<int> >q;
ll ans;
int main(){
    sci(n);
    rep(i,1,n){
        sci(a[i]);
    }
    rep(i,0,18){
        ok[1<<i]=1;
    }
    per(i,n,1){
        if(a[i]==-1)break;
        q.push(a[i]);
        if(ok[i]){
            ans+=q.top();
            q.pop();
        }
    }
    printf("%lld\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章