AtCoder ABC 062 D. Score Attack (优先队列)

英文题解:

总之就是一个非常经典的优先队列问题,前K大和。

前缀和优化处理一下,时间复杂度(NlogN)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;

#define bug printf("bug\n");
#define bug2(var) cout<<#var<<" "<<var<<endl;

typedef long long ll;

const int maxn = 300010;

int n;
ll a[maxn],pre[maxn],aft[maxn];

priority_queue<ll> y; // 大根堆 
priority_queue<ll, vector<ll>,greater<ll> > x; // 小根堆 

ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }

int main(){
    n = read();
    for(int i = 1;i <= 3*n ;i++) { a[i] = read(); }
     
    for(int i = 1;i <= n;i++){
        x.push(a[i]);
        pre[i] = pre[i-1] + a[i];
    }
    
    
    for(int i = n + 1;i <= 2 * n; i++) {
        int cur = x.top(); 
        pre[i] = pre[i-1];
        if(a[i] > cur){
            x.pop();
            pre[i] -= cur;
            pre[i] += a[i];
            x.push(a[i]);
        }
    }
    
//    for(int i=1;i<=2*n;i++){
//        printf("%d ",pre[i]);
//    }printf("\n");
    
    for(int i = 3 * n; i >= 2 * n + 1 ;i--){
        y.push(a[i]);
        aft[i] = aft[i+1] + a[i];
    }
        
//    bug
    
    for(int i = 2 * n; i > n ;i--){
        int cur = y.top();
        aft[i] = aft[i+1];
        if(a[i] < cur){
            y.pop();
            aft[i] -= cur;
            aft[i] += a[i];
            y.push(a[i]);
        }
    }
    
//    for(int i=3*n;i>n;i--){
//        printf("%d ",aft[i]);
//    }printf("\n");
    
    ll ans = -1000000000000000ll;
    for(int i = n;i <= 2 * n;i++){
        ans = max(ans , pre[i] - aft[i+1]);
//        bug2(ans);
    }
    
    printf("%lld\n",ans);
    
    return 0;
}
原文地址:https://www.cnblogs.com/tuchen/p/13420127.html