1. 程式人生 > >Codeforces Round #519 by Botan Investments E. Train Hard, Win Easy(思維+貪心)

Codeforces Round #519 by Botan Investments E. Train Hard, Win Easy(思維+貪心)

題目連結

題意

每個人都可以解決A題和B題,得分分別是 x i x_i y i

y_i ,他可以任意和他不討厭的人組隊,一個隊伍中每個人都只能做 A A B B 中的一道題,且每道題都只能由一個人來完成,隊伍中兩道題得分的總和越少越好。求出每個人所參與的所有隊伍的得分總和。

題解

現在有c和d兩個人組隊,他們對於A題和B題的得分分別是, x c , y c x_c,y_c

x d , y d x_d,y_d 。c可以做A題的條件是 x c + y d x d + y c x_c+y_d \leq x_d+y_c 。移項一下變成 y d x d y c x c y_d-x_d \leq y_c-x_c 。 所以我們可以按照每個人 y x y-x 進行排序,假設現在計算第i個人的得分,那麼如果他和前 i 1 i-1 個人組隊的話,他一直做的都是A題和後 n i + 1 n-i+1 個人組隊的話做的都是B題。再分別求 x x y y 的字首和就可以做到 O ( 1 ) O(1) 計算一個人的得分。最後再根據討厭的關係減一減就可以了。

程式碼

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+5;

struct node {
    ll x,y;
    int id;
    ll val;
    bool operator <(const node& rhs) const {
        return val < rhs.val;
    }
}a[maxn], b[maxn];

ll prex[maxn], prey[maxn];
ll ans[maxn];
int n,m;
ll get(ll x, ll _x, ll _y, int pos) {
    ll px = pos;
    // cout << px <<" ";
    ll ret = 0;
    ret += prey[px]+_x*px;
    // cout << ret <<" ";
    ret += prex[n]-prex[px]+_y*(n-px);
    // cout << ret <<" ";
    ret -= (_x+_y);
    // cout << ret <<endl;
    
    return ret;
}
int main() {
    
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        scanf("%lld%lld", &a[i].x, &a[i].y);
        a[i].val = a[i].y-a[i].x;
        b[i].x = a[i].x; b[i].y = a[i].y;
        a[i].id = i;
    }
    sort(a+1,a+n+1);
    // cout << a[4].val << endl;
    for(int i = 1; i <= n; ++i) {
        prex[i] = prex[i-1]+a[i].x;
        prey[i] = prey[i-1]+a[i].y;
    }
    for(int i = 1; i <= n; ++i) {
        // cout <<i <<" ";
        ans[a[i].id] = get(a[i].y-a[i].x, a[i].x, a[i].y, i);
        // cout << endl;
    }
    for(int i = 0; i < m; ++i) {
        ll u,v;
        scanf("%lld%lld", &u, &v);
        ll ret = min(b[u].x+b[v].y, b[u].y+b[v].x);
        // cout << ret << endl;
        ans[u] -= ret;
        ans[v] -= ret;
    }
    for(int i = 1; i <= n; ++i)
        cout << ans[i] <<" ";
    cout << endl;
    return 0;
}