妙妙题,但是感觉评不到紫。
题目链接。
题意
luogu 题意。
有 \(n\) 个人,贿赂第 \(i\) 个人的代价为 \(a_i\)。这些人中,贿赂代价为 \(-1\) 的是你的朋友。现在,你可以两两配对,使得编号小的被淘汰,但是,如果你贿赂了编号大的,那么编号大的被淘汰,而编号小的留下。问:使得你朋友夺得冠军的最小代价。
题解
如果你的朋友不是第 \(n\) 个人,则必然要贿赂第 \(n\) 个人。
此时若你的朋友编号 \(\ge \frac{n}{2}\),则完成。否则需要取 \(\frac{n}{2}\sim n-1\) 的最小贿赂代价。
容易发现规律,即每 \(2^k\) 分一段,每一段取 \(a_i\) 最小值,直到 \(a_i=-1\) 停止。
时间复杂度 \(O(n)\)。
总结
巨大妙妙。但是手算一下应该不难看出。
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define sz(x) (int)x.size()
#define ll long long
#define pii pair<int,int>
using namespace std;
inline void chmin(int &x,int y){x=min(x,y);}
inline void chmax(int &x,int y){x=max(x,y);}
const int N=(1<<18)+5;
int n;
ll a[N];
priority_queue<ll,vector<ll>,greater<ll>> pq;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",a+i);
ll ans=0;
for(int i=n;i>=1;i--){
if(a[i]==-1) break;
pq.push(a[i]);
if(__builtin_popcount(i)==1){
ans+=pq.top();
pq.pop();
}
}
printf("%lld\n",ans);
return 0;
}
/*
Basic:
1. int or long long?
2. freopen?
3. memory limits?
Advanced:
1. use more functions
2. write carefully and check
3. think twice before writing
4. debug quickly
5. never copy others' codes
*/
标签:pq,int,题解,Tournament,long,CF1260E,编号,贿赂,define
From: https://www.cnblogs.com/Jerry-Jiang/p/CF1260E.html