这周刷了几道有关的题目,小小的写一个对Exchange Argument
思想的理解和总结,欢迎大佬来吊打我。
Exchange Argument(或许可以翻译为交换论证?)是一种贪心地构造最优序列的思想。通常这类题目会有
sorting
,greedy
这类标签。它适用于在一个操作序列中,找到最优的操作顺序。通常会通过定义一个权值比较器,对所有操作按一定标准排序来完成这一过程。
通常定义的权值比较器需要满足以下两个性质:
- 传递性,即 x < y ∧ y < z ⇒ x < z x<y\land y<z \Rightarrow x<z x<y∧y<z⇒x<z,这使得权值满足全序关系,可以排序。
- 交换性,即 x < y ⇒ y > x x<y\Rightarrow y>x x<y⇒y>x,这样保证排序结果唯一。
口胡完毕,来看一道典型题。
要求大臣们的最优顺序,考虑相邻的两个大臣 i i i、 j j j,设它们之前所有人左手之积为 A A A,考虑交换它们两个,对前后并不会造成影响,只会对它们本身的取值有影响。列式可得,当 i i i 在 j j j 前更优,一定满足:
max ( A b i , A × a i b j ) < max ( A b j , A × a j b i ) \max(\frac{A}{b_i},\frac{A\times a_i}{b_j})<\max(\frac{A}{b_j},\frac{A\times a_j}{b_i}) max(biA,bjA×ai)<max(bjA,biA×aj)
展开:
( 1 b i < 1 b j ∧ a i b j < 1 b j ) ∨ ( 1 b i < a j b i ∧ a i b j < a j b i ) (\frac{1}{b_i}<\frac{1}{b_j}\land \frac{a_i}{b_j}<\frac{1}{b_j})\lor (\frac{1}{b_i}<\frac{a_j}{b_i}\land \frac{a_i}{b_j}<\frac{a_j}{b_i}) (bi1<bj1∧bjai<bj1)∨(bi1<biaj∧bjai<biaj)
化简逻辑条件,剩下:
a i × b i < a j × b j a_i\times b_i<a_j\times b_j ai×bi<aj×bj
所以将所有大臣以 a × b a\times b a×b 为权值升序排序,然后模拟一下过程求出答案。(以下代码省略150行的高精模板)
int n;
struct Person//定义类
{
ll l,r;
bool operator<(Person &B)//权值比较器
{
return (l*r)<(B.l*B.r);
}
}a[1005],k;
Int ans;
int main()
{
scanf("%d%lld%lld",&n,&k.l,&k.r);
for(int i=0;i<n;i++)
scanf("%lld%lld",&a[i].l,&a[i].r);
sort(a,a+n);//按权值升序排序
Int pro=k.l;
for(int i=0;i<n;i++)//模拟过程
{
Int q=pro/a[i].r;
if (q>ans)
ans=q;
pro*=(Int)a[i].l;
}
printf("%lld", ans.s[ans.s[0]]);//输出高精度变量
for(int i = ans.s[0] - 1; i >= 1; i--)
printf("%09lld", ans.s[i]);
putchar('\n');
return 0;
}
时间复杂度: O ( n log n ) \operatorname O(n\log n) O(nlogn)
空间复杂度: O ( n ) \operatorname O(n) O(n)
考虑顺序固定时,用 dp 求总时间。
{ d p a i = d p a i − 1 + a i d p b i = max ( d p a i , d p b i − 1 ) + b i d p c i = max ( d p b i , d p c i − 1 ) + c i \begin{cases}dpa_i=dpa_{i-1}+a_i\\dpb_i=\max(dpa_i,dpb_{i-1})+b_i\\dpc_i=\max(dpb_i,dpc_{i-1})+c_i\end{cases} ⎩⎪⎨⎪⎧dpai=dpai−1+aidpbi=max(dpai,dpbi−1)+bidpci=max(dpbi,dpci−1)+ci
总时间为 d p