【】queue
【链接】点击打开链接
【题意】
实话实说,给 OIER 大神们排队这种工作是最让人头疼的事情了。因为同学们都有自尊 心,都不愿意排后面。 现在共有 n 个同学要排成一列,每个同学有两个属性:影响力和承受能力。给一个同学 造成的心理创伤指数等于所有在他前面同学的影响力之和减去他的承受能力。 请你帮忙安排一下点名顺序,尽量使受到心理创伤最大的同学少受创伤。
1≤n≤50000,1≤影响力≤10000,1≤承受能力≤10^9
【题解】
假设n个人的位置已经随便安排好了(不一定最优);
考虑两个相邻的人i,j;(i<j)
我们下面讨论这两个人要交换位置的条件是什么;
假设他们的影响力和承受力分别为a[],b[],然后1..max(i,j)这些人中,除了这两个人之外,a[]的和为sum.
则
假设顺序是i,j;
则i所受伤害为sum-b[i],j所受伤害为sum+a[i]-b[j]
假设顺序是j,i
则j所受伤害为sum-b[j],i所受伤害为sum+a[j]-b[i]
要比较的是
max(sum-b[i],sum+a[i]-b[j])和
max(sum-b[j],sum+a[j]-b[i]);
因为
sum-b[i]<sum+a[j]-b[i];
sum-b[j] <sum+a[i]-b[j];
则我们只需要再比较一下sum+a[i]-b[j]和sum+a[j]-b[i]的值就好了.
因为
如果sum+a[i]-b[j]<sum+a[j]-b[i] ①
图中箭头指向的是较大的那个。
会发现,sum+aj-b[i]会是那个最大的数字.
然后前者会都比那个最大值小。
(而前者是按(i,j)的顺序放的)
说明按照(i,j)的顺序放,得到的最大值比较小。
(如果①式反过来..显然就是(j,i)这样放比较小了)
所以如果①式成立
也即a[i]-b[j]<a[j]-b[i]
->a[i]+b[i]<a[j]+b[j]
则按照(i,j)顺序放;
否则调换(i,j)顺序。
则一开始就按照a+b的值升序排一下,就能确定最后的顺序了。
【错的次数】
0
【反思】
在这了写反思
【代码】
#include <bits/stdc++.h> using namespace std; const int N = 5e4; int n,a[N+10],b[N+10]; pair <int, int> c[N + 10]; int main() { // freopen("F:\\rush.txt", "r", stdin); ios::sync_with_stdio(0), cin.tie(0); cin >> n; for (int i = 1; i <= n; i++) { cin >> a[i] >> b[i]; c[i].first = a[i] + b[i], c[i].second = i; } sort(c + 1, c + 1 + n); int ans = 0 - b[c[1].second],temp = 0; for (int i = 2; i <= n; i++) { temp += a[c[i - 1].second]; ans = max(ans, temp - b[c[i].second]); } cout << ans << endl; return 0; }