标签:策略 algo header limit cow i++ 奶牛 ++ 排序
\[ \texttt{Description} \]
有 \(n\) 头牛,每头牛都有自己的体重 \(W_i\) 和力量 \(S_i\) 。
将这 \(n\) 头牛摞在一起,每头牛的压扁指数定义为:压在该牛上面的牛的体重之和 \(-\) 该牛力量 。
您需要找到一种摞牛方案,使得压扁指数最大的牛的压扁指数最小。
求这个压扁指数。
\[
\texttt{Solution}
\]
微扰(邻项交换)证明贪心好题。
记 \(Z_i=\sum\limits_{j=1}\limits^{i}W_j\)(前 \(i\) 头牛体重和)。
我们考虑任意一个邻项,考虑交换:
第 \(i\) 头牛 | 第 \(i+1\) 头牛 | |
---|---|---|
交换前压扁指数 | \(Z_{i-1}-S_i\) | \(Z_{i-1}+W_i-S_{i+1}\) |
交换后压扁指数 | \(Z_{i-1}-S_{i+1}\) | \(Z_{i-1}+W_{i+1}-S_i\) |
\[ \max(Z_{i-1}-S_i,Z_{i-1}+W_i-S_{i+1}) \\ \max(Z_{i-1}-S_{i+1},Z_{i-1}+W_{i+1}-S_i) \]
\[ \max(-S_i,W_i-S_{i+1}) \\ \max(-S_{i+1},W_{i+1}-S_i) \]
\[ \max(S_{i+1},W_i+S_i) \\ \max(S_i,W_{i+1}+S_{i+1}) \]
\[ W_i+S_i \\ W_{i+1}+S_{i+1} \]
当 \(W_i+S_i \geq W_{i+1}+S_{i+1}\) 时,上式 \(\geq\) 下式,则交换后定不比交换前劣。
至此我们就有一个贪心策略:将这 \(n\) 头牛以 \(W_i+S_i\) 为关键字从小到大排序。尽管这个贪心策略很玄学。
\(\mathcal{O(n \log n)}\) 。
\[ \texttt{Code} \]
#include<cstdio>
#include<algorithm>
#define RI register int
using namespace std;
inline int read()
{
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-f;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x*f;
}
const int N=50010;
int n;
struct Cow{
int W,S;
}a[N];
bool cmp(Cow a,Cow b)
{
return a.W+a.S<b.W+b.S;
}
long long ans=-0x3f3f3f3f;
int main()
{
n=read();
for(RI i=1;i<=n;i++)
a[i].W=read(),a[i].S=read();
sort(a+1,a+1+n,cmp);
long long sum=0;
for(RI i=1;i<=n;i++)
{
ans=max(ans,sum-a[i].S);
sum+=a[i].W;
}
printf("%lld\n",ans);
return 0;
}
\[ \texttt{Thanks} \ \texttt{for} \ \texttt{watching} \]
标签:策略 algo header limit cow i++ 奶牛 ++ 排序
原文地址:https://www.cnblogs.com/cjtcalc/p/12369834.html