题目链接:https://vjudge.net/problem/POJ-3045
题意:n个奶牛堆成一堆,每个都有重量和力气,奶牛i的危险值=i上方奶牛的总重量减去i的力气,求最大危险值的最小值。n<=50000
看到进阶指南上写了个邻项交换,大概就知道怎么想了。考虑两头奶牛p和q(其实就是比较函数cmp的写法):
1)若a[p].w>=a[q].w且a[p].s>=a[q].s,将p堆到q下面,若a[p].w<=a[q].w且a[p].s<=a[q].s将p堆到q上面 2)其他情况,设上方奶牛的总重为c。若p在上q在下,p的危险值为c-a[p].s,q的危险值为c+a[p].w-a[q].s,令rp=max(-a[p].s,a[p].w-a[q].s),同理若q在上p在下,令rq=max(-a[q].s,a[q].s-a[p].s)。显然若rp<rq则把p放在上面,否则把q放在上面。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=500+10; 6 struct st{ int w,s;}a[maxn]; 7 int n,i,ans,sum; 8 9 bool cmp(st p,st q){ 10 if (p.w>=q.w&&p.s>=q.s) return true; 11 else if (p.w<=q.w&&p.s<=q.s) return false; 12 else{ 13 int rp=max(-q.s,q.w-p.s); 14 int rq=max(-p.s,p.w-q.s); 15 return rp<rq; 16 } 17 } 18 19 int main(){ 20 scanf("%d",&n); 21 for (i=1;i<=n;i++) scanf("%d%d",&a[i].w,&a[i].s); 22 sort(a+1,a+n+1,cmp); 23 for (i=2;i<=n;i++) sum+=a[i].w; 24 ans=-1e9; 25 for (i=1;i<=n-1;i++) { 26 ans=max(ans,sum-a[i].s); 27 sum-=a[i+1].w; 28 } 29 ans=max(ans,-a[n].s); 30 printf("%d\n",ans); 31 return 0; 32 }