codeforces 1043 E. Train Hard, Win Easy
阿新 • • 發佈:2018-11-23
題目
傳送門
題意:
有n個人,m個排斥關係,有一個競賽,有兩道題目,給出n個人做兩道題的做題速度,然後求分別這n個人做題時間累積的最小值。每個人只能做一道題,下一個題目必須他的同伴來做。有排斥關係的兩個人不能相互組隊。
思路:
設i的做題時間分別為xi,yi,j的做題時間分別為xj,yj。
若讓i做第一題,j做第二題,則必須滿足以下不等式:
xi+yj<xj+yi; 則 xi-yi<xj-yj, 只要是滿足xj-yj>xi-yi的形式一定是i做第一題。
同理,i做第二題,j做第一題也是一樣的做法。
然後再減去相互排斥的人就可以了。
程式碼如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <vector> using namespace std; typedef long long ll; const int maxn=3*1e5+5; int n,m; struct score { ll a,b,t; int id; }; score a[maxn],b[maxn]; int loc[maxn]; ll suma[maxn],sumb[maxn]; ll Min[maxn]; vector<int>v[maxn]; int compare (score a,score b) { return a.t<b.t; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%lld%lld",&a[i].a,&a[i].b); a[i].t=a[i].a-a[i].b; a[i].id=i; b[i]=a[i]; } sort (a+1,a+n+1,compare); suma[0]=0; sumb[0]=0; for (int i=1;i<=n;i++) { suma[i]=suma[i-1]+a[i].a; sumb[i]=sumb[i-1]+a[i].b; } for (int i=1;i<=n;i++) { ll temp1=0,temp2=0,temp=0; temp1=sumb[n]-sumb[i]+(n-i)*a[i].a; temp2=suma[i-1]+(i-1)*a[i].b; Min[a[i].id]=temp1+temp2; } for (int i=0;i<m;i++) { int x,y; scanf("%d%d",&x,&y); ll t=min(b[x].a+b[y].b,b[x].b+b[y].a); Min[x]-=t; Min[y]-=t; } for (int i=1;i<=n;i++) { printf("%lld%c",Min[i],i==n?'\n':' '); } return 0; }