P2123 皇后游戏

题目 P2123 皇后游戏

思路:贪心(微扰/邻项交换)

微扰/邻项交换:证明在任意局面下,任何对局部最优解的微小改变都会造成整体结果变差,经常用于以“排序”为贪心策略的证明。
注意:排序的 > > > o r or or < < <必须满足严格弱序传递性(即可以传递到整体而非局部相邻才满足此不等式)

建议参考这篇博客:传送门
题目描述
设前一项为 i i i,后一项为 j ( i + 1 ) j(i+1) ji+1,设 C i − 1 C_{i-1} Ci1 y y y,设 ∑ j = 1 i − 1 \sum\limits_{j=1}^{i-1} j=1i1 x x x
由上图可得:
交换前: C i = m a x ( y , x + a i ) + b i C_i=max(y,x+a_i)+b_i Ci=max(y,x+ai)+bi
C i + 1 = m a x ( C i , x + a i + a j ) + b j C_{i+1}=max(C_i,x+a_i+a_{j})+b_j Ci+1=max(Ci,x+ai+aj)+bj
交换后: C i = m a x ( y , x + a j ) + b j C_i=max(y,x+a_j)+b_j Ci=max(y,x+aj)+bj
C i + 1 = m a x ( C i , x + a i + a j ) + b i C_{i+1}=max(C_i,x+a_i+a_{j})+b_i Ci+1=max(Ci,x+ai+aj)+bi
则交换前: C i + 1 = m a x { y + b i + b i + 1 , x + a i + b i + b i + 1 , x + a i + a i + 1 + b i + 1 } C_{i+1}=max\{y+b_i+b_{i+1},x+a_i+b_i+b_{i+1},x+a_i+a_{i+1}+b_{i+1}\} Ci+1=max{y+bi+bi+1,x+ai+bi+bi+1x+ai+ai+1+bi+1} ⋯ \cdots ① ①
交换后: C i + 1 = m a x { y + b i + b i + 1 , x + a i + 1 + b i + b i + 1 , x + a i + a i + 1 + b i } C_{i+1}=max\{y+b_i+b_{i+1},x+a_{i+1}+b_i+b_{i+1},x+a_i+a_{i+1}+b_{i}\} Ci+1=max{y+bi+bi+1,x+ai+1+bi+bi+1x+ai+ai+1+bi} ⋯ \cdots ② ②
比较上面两式:发现都有一项为: y + b i + b i + 1 y+b_i+b_{i+1} y+bi+bi+1,故舍掉 TAT不知道怎么证明,有证明麻烦dd
① ① 进行化简: C i + 1 = x + a i + b i + 1 + m a x { b i , a i + 1 } C_{i+1}=x+a_i+b_{i+1}+max\{ b_i,a_{i+1}\} Ci+1=x+ai+bi+1+max{bi,ai+1}
② ② 进行化简: C i + 1 = x + a i + 1 + b i + m a x { b i + 1 , a i } C_{i+1}=x+a_{i+1}+b_{i}+max\{ b_{i+1},a_{i}\} Ci+1=x+ai+1+bi+max{bi+1,ai}
假设不交换更优,则有 ① ≤ ② ①\le②
移项化简得:
m a x { b i , a j } − a j − b i ≤ m a x { b j , a i } − a i − b j max\{b_i,a_j\}-a_j-b_i\le max\{b_j,a_i\}-a_i-b_j max{bi,aj}ajbimax{bj,ai}aibj
相当于: − m i n { a j , b i } ≤ − m i n { a i , b j } -min\{a_j,b_i\}\le -min\{a_i,b_j\} min{aj,bi}min{ai,bj}
即: m i n { a i , b j } ≤ m i n { a j , b i } min\{a_i,b_j\}\le min\{a_j,b_i\} min{ai,bj}min{aj,bi} ⋯ ③ \cdots③
即假设不交换 ( i (i (i j j j ) ) )更优时满足 ③ ③ ,我们注意到, ③ ③ 的符号是 ≤ \le ,不满足非自反性,即不满足传递性,所以我们要分类讨论使其对任一情况均适用。
感觉luogu此人题解思路很妙
题解链接感谢大佬

latex写吐了,终于到了我们最爱的代码时间
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t; 
const int N=2e4+50;
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')	f=-f;c=getchar();}
	while(isdigit(c)){cnt=(cnt<<3)+(cnt<<1)+(c^48);c=getchar();}
	return cnt*f;
}
struct node{
	int a,b,k;
	bool operator <(node now) const{//重载运算符大法好!!!
		if(k!=now.k)	return k<now.k;
		if(k<=0)	return a<now.a;
		return b>now.b;
	}
}per[N];
signed main(){
	t=read();
	while(t--){
		int n;n=read();
		for(int i=1;i<=n;++i){
			per[i].a=read();per[i].b=read();
			if(per[i].a>per[i].b)
				per[i].k=1;
			else if(per[i].a<per[i].b)
				per[i].k=-1;
			else
				per[i].k=0;
		}
		sort(per+1,per+1+n);
		int s[N];memset(s,0,sizeof(s));
		int ans=-0x3f3f;
		for(int i=1;i<=n;i++){
			s[i]=s[i-1]+per[i].a;
			ans=max(ans,s[i])+per[i].b;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

自己对邻项交换的理解:

  1. 根据题意推出公式,并按分析出的公式进行排序使其满足条件(传递性,非自反性 ⋯ \cdots )(分类讨论大法好),最后因为已经排序,直接计算第 n n n项即可。
  2. 如何排序:满足题意(最优解)的条件是对于任意 i , j i,j i,j都满足我们已经推出的公式,进行操作使任意 i , j i,j i,j都满足这个公式即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值