P8253 [NOIO 2022 tg] 如何正确地排序

题面

有一个 \(m\times n\) 的数组 \(a_{i,j}\),定义:

\[f(i,j)=\min\limits_{k=1}^m(a_{k,i}+a_{k,j})+\max\limits_{k=1}^m(a_{k,i}+a_{k,j}) \]

你需要求出 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^nf(i,j)\)

数据范围: \(m\le 4,n\le2\times 10^5,a_{i,j}\le 2\times 10^5\)

题解

典型考场降智型选手。

想到单独考虑 \(\min,\max\) ,想到考虑每个数产生贡献的次数,为什么不把所有式子都列出来啊...

\[a_i+a_j\le b_i+b_j\\ a_i+a_j\le c_i+c_j\\ a_i+a_j\le d_i+d_j \]

\(a_i+a_j\le b_i+b_j\) 为例:\(a_i+a_j\le b_i+b_j\Leftrightarrow a_i-b_i\le b_j-a_j\) ,所以设 \(A_i=a_i-b_i\)\(B_i,C_i\) 同理。

那么原来的式子就变成了:

\[A_i\le -A_j\\ B_i\le -B_j\\ B_i\le -C_j \]

这你还不会吗?

一些细节:

  • 可以把每个元素拆成修改和查询,修改点每个权值取反。
  • 防止出现最大值相同而算重,可以给之前已经处理的元素+1。
  • 求最大值的式子和上面只有符号的区别,因此可以全部取反再算一次。
void solve(int op){
	for(int I=0;I<m;++I){
		k=0;
		for(int i=1;i<=n;++i){
			a[++k].op=A[I][i];
			for(int j=0;j<m;++j)
				if(j^I)a[k].f[j-(j>I)]=(A[I][i]-A[j][i])*op-(I>j);
			a[++k].op=0;
			for(int j=0;j<m;++j)
				if(j^I)a[k].f[j-(j>I)]=(A[j][i]-A[I][i])*op;
		}
		sort(a+1,a+1+k,paix);
		solve2(1,k);
	}
}

启发

  • 感觉这种题不要再想一些奇奇怪怪的做法,先老老实实把式子推了,说不定就有解法了。
posted @ 2022-03-27 11:39  qwq_123  阅读(88)  评论(0编辑  收藏  举报