http://acm.hdu.edu.cn/showproblem.php?pid=4296
此题仅需用 w+s 的值进行从小到大的排序即可 注意 结果可能超32位
证明 只需要证明相邻的即可 因为它们不会影响前面的PDV 也不会影响后面的PDV
假设 w1+s1 < w2+s2 在此之前的的w和为 X
那么 w1+s1 在前则 最大PDV 为 P1=max(X-s1,X+w1-s2);
如果 w2+s2 在前则 最大PDV 为 P2=max(X-s2,X+w2-s1);
我们可以同时把X去掉 则
P1=max( -s1,w1-s2);
P2=max( -s2,w2-s1);
再将所有值加上 s1+s2 则
P1=max(s2,w1+s1);
P2=max(s1,w2+s2);
那么P2 和 P1 那个小呢
因为有 w2+s2>w1+s2 且 w2+s2>=s2
所有P2>P1
所以我们要P1的值 也就是将和小的排在前面 如果相等 会发现顺序无关
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> #define LL long long //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int INF=0x5fffffff; const int N=100005; struct node { int w,s; }mem[N]; bool cmp(node x,node y) { return (x.w+x.s)<(y.w+y.s); } int main() { //freopen("data.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) { for(int i=1;i<=n;++i) { scanf("%d %d",&mem[i].w,&mem[i].s); } sort(mem+1,mem+1+n,cmp); mem[0].s=mem[0].w=0; LL ans=0; LL temp=0; for(int i=1;i<=n;++i) { temp=temp+mem[i-1].w+mem[i-1].s-mem[i].s; if(temp>ans) ans=temp; } cout<<ans<<endl; } return 0; }