Codeforces Round #519 by Botan Investments E. Train Hard, Win Easy(思維+貪心)
阿新 • • 發佈:2018-11-01
題意
每個人都可以解決A題和B題,得分分別是 和 ,他可以任意和他不討厭的人組隊,一個隊伍中每個人都只能做 和 中的一道題,且每道題都只能由一個人來完成,隊伍中兩道題得分的總和越少越好。求出每個人所參與的所有隊伍的得分總和。
題解
現在有c和d兩個人組隊,他們對於A題和B題的得分分別是,
和
。c可以做A題的條件是
。移項一下變成
。 所以我們可以按照每個人
進行排序,假設現在計算第i個人的得分,那麼如果他和前
個人組隊的話,他一直做的都是A題和後
個人組隊的話做的都是B題。再分別求
和
的字首和就可以做到
計算一個人的得分。最後再根據討厭的關係減一減就可以了。
程式碼
#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;
}