首页 > 其他分享 >题解 P5426 [USACO19OPEN]Balancing Inversions G

题解 P5426 [USACO19OPEN]Balancing Inversions G

时间:2023-07-17 21:35:37浏览次数:33  
标签:val cdot 题解 sl1 tot int sr1 Inversions P5426

来一篇简单易懂的良心题解。

由于数值不是 \(0\) 就是 \(1\),我们可以考虑将逆序对的统计方式化简。

以左区间为例,设 \(x\) 为 \(1\) 的个数,\(p_i\) 为第 \(i\) 个 \(1\) 的坐标,则逆序对个数为 \(\sum\limits_{i=1}^{x}n-p_i-(x-i)\)。也就是 \((n-x)\cdot x+\frac{x\cdot (x+1)}{2}-\sum\limits_{i=1}^{x}p_i\)。

右区间同理。

题目要求两个区间的逆序对个数相同,所以我们把两个式子联立起来。

\((n-x)\cdot x+\frac{x\cdot (x+1)}{2}-\sum\limits_{i=1}^{x}p_i=(n-y)\cdot y+\frac{y\cdot (y+1)}{2}-\sum\limits_{i=1}^{y}p2_i\)

令 \(val(d)=(n-d)\cdot d+\frac{d\cdot (d+1)}{2}\)。

则 \(\sum\limits_{i=1}^{x}p_i-\sum\limits_{i=1}^{y}p2_i=val(x)-val(y)\)。

现在考虑怎么把 \(t\) 个 \(1\) 从左区间移动到右区间。(右到左同理)

我们可以把左区间最右边的 \(t\) 个 \(1\) 移到左区间最靠右的 \(t\) 个位置,再把右区间最左边的 \(t\) 个 \(0\) 移到右区间最靠左的 \(t\) 个位置,接着再用 \(t^2\) 次交换调换 \(01\) 的位置即可。

而将若干个 \(0\) 或 \(1\) 移到某一端的交换次数可以通过预处理 \(O(1)\) 计算出来。

定义 \(sl0_i\) 表示左区间最靠右的 \(i\) 个 \(0\) 的坐标之和,\(sr0_i\) 表示右区间最靠左的 \(i\) 个 \(0\) 的坐标之和。(\(sl1_i\) 和 \(sr1_i\) 同理)

接下来我们枚举完成所有交换操作后左区间 \(1\) 的个数 \(x'\),然后调整若干个 \(1\) 所在的区间,再在区间内进行微调使两边 \(1\) 的坐标的差值符合要求。

令 \(c=|x-x'|\)。

如果 \(x'<x\),则交换次数为

\(\frac{(n - c + 1 + n) \cdot c}{2} - sl1_c + sr0_c - \frac{c \cdot (c + 1)}{2} + c^2 + |sl1_x - sl1_c - sr1_y - sr0_c - val(x') + val(y + c)|\)

否则,交换次数为

\(\frac{(n - c + 1 + n) \cdot c}{2} - sl0_c + sr1_c - \frac{c \cdot (c + 1)}{2} + c ^ 2 + |sl1_x + sl0_c - sr1_y + sr1_c - val(x') + val(y - c)|\)

最后取个最小值就行了。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
ll n, a[N], b[N], x = 0, y = 0, sl0[N], sl1[N], sr0[N], sr1[N], minn = 1e9, tot;
int val(int d) {return (n - d) * d + d * (d + 1) / 2;}
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; ++i) {cin >> a[i]; if (a[i]) ++x;}
	for (int i = 1; i <= n; ++i) {cin >> b[i]; if (b[i]) ++y;}
	tot = 0; for (int i = n; i >= 1; --i) {if (!a[i]) sl0[tot + 1] = sl0[tot] + i, ++tot;}
	tot = 0; for (int i = 1; i <= n; ++i) {if (!b[i]) sr0[tot + 1] = sr0[tot] + i, ++tot;}
	tot = 0; for (int i = n; i >= 1; --i) {if (a[i]) sl1[tot + 1] = sl1[tot] + i, ++tot;}
	tot = 0; for (int i = 1; i <= n; ++i) {if (b[i]) sr1[tot + 1] = sr1[tot] + i, ++tot;}
	for (int xx = 0; xx <= x + y; ++xx) {
		if (xx > n || x + y - xx > n) continue;
		ll c, num;
		if (xx < x) {
			c = x - xx;
			num = (n - c + 1 + n) * c / 2 - sl1[c] + sr0[c] - c * (c + 1) / 2 + c * c + abs(sl1[x] - sl1[c] - sr1[y] - sr0[c] - val(xx) + val(y + c));
		} else {
			c = xx - x;
			num = (n - c + 1 + n) * c / 2 - sl0[c] + sr1[c] - c * (c + 1) / 2 + c * c + abs(sl1[x] + sl0[c] - sr1[y] + sr1[c] - val(xx) + val(y - c));
		}
		minn = min(minn, num);
	}
	cout << minn << endl;
	return 0;
}

这么良心的题解,点个赞再走吧 QWQ

标签:val,cdot,题解,sl1,tot,int,sr1,Inversions,P5426
From: https://www.cnblogs.com/HQJ2007/p/17561288.html

相关文章

  • 题解 Friendly Spiders
    FriendlySpiders带有技巧的最短路。如果\(u\)能到\(v\),说明\(\gcd(u,v)>1\),也就是有相同因子。所以我们考虑对于每个数\(u\),向他的所有质因子连一条长度为\(1\)的边,这样我们从\(u\)到\(v\)需要走两步,最终答案除以\(2\)即可。每次遇到一个新的因子,都要新建节点。......
  • 题解 The Human Equation
    TheHumanEquation思维题。我们考虑每次\(a\)数组加一减一对于其前缀和\(sum\)的影响。可以发现,假设相邻两次加一和减一的位置分别为\(l\)和\(r\),那么\(sum\)在\([l,r)\)内会加一。先减后加也同理。所以,一次加减操作相当于将\(sum\)若干段连续序列加一或减一。......
  • 题解 [ARC153B] Grid Rotations
    [ARC153B]GridRotations有思维含量的一题。我们横纵坐标分开考虑,对于每一个矩形,每次操作会使其内部元素的横坐标上下对调。纵坐标也同理,左右对调。而这种反转操作我们显然可以直接用两棵文艺平衡树维护,复杂度\(O(n\logn)\)。标程的做法更巧妙一下。我们可以把一条链收尾......
  • 题解 Yet Another Minimization Problem
    YetAnotherMinimizationProblem神仙题。第一眼看上去就是DP。定义\(f_{i,j}\)表示当前点\(i\),分\(j\)段的最小费用。\(f_{i,j}=\min(f_{i,j},f_{k,j-1}+val_{k+1,i})\)然后发现复杂度\(O(n^2k)\),直接T飞,需要优化。我们发现\(j\)那一维可以滚掉,也就是只考虑第......
  • 题解 P4322 [JSOI2016]最佳团体
    P4322[JSOI2016]最佳团体分数规划+树形背包。可以根据推荐关系建出一颗树,然后如果选了一点,则该点到根上的所有点都必须选。二分\(mid\),定义每个结点的权值,然后判断选\(k+1\)个节点的最大值是否大于\(0\)。设\(f_{i,j}\)为当前节点\(i\),在其子树内选了\(j\)个节点,最......
  • 题解 Bracket Insertion
    BracketInsertion神仙DP题,不愧是tourist。容易发现,括号序列一共有\(1\cdot3\cdot5...\cdot(2n-1)\)种生成方式。假如(为\(1\),)为\(-1\),那么一个序列合法的充要条件为:最小前缀和为\(0\),且以\(0\)结尾。现在考虑维护这些前缀和。如果我们在当前序列某一位后插......
  • 题解 P2276 [HNOI2002]农场的果树
    首先可以观察出一颗\(n\)个节点的二叉树,当其字典序最小的时候,其形态为一条向右偏的链,当其字典序最大的时候,是一条向左偏的链。由于每一种编码对应唯一的一颗二叉树,我们可以先建树。然后考虑树上分治,尝试以下三种方式:变大右子树的字典序变大左子树的字典序,并将右子树变成......
  • 题解 P7640 [BalticOI 2006 Day 2] CITY PLANNING
    首先我们定义“圈”为与原点距离相等的点集。...3.....323...32123.3210123.32123...323.....3...暴力:把圈放到堆里,然后每次取出代价最小的一圈,修改当前圈的楼层,向外圈拓展。正解:考虑二分。如果是二分最终答案,我们会发现......
  • 题解 P7250 [BalticOI 2012 Day1] 山峰
    通过观察,可以发现此题和最小生成树十分相似(两个地点之间途经的最小值最大)。于是可以考虑这么做:通过bfs将每一个块预处理出来,并记录其编号、高度、类型(是否为高地)以及边缘的点。将每一个块按高度从大到小排序。依次枚举每个块:对于当前要处理的块,枚举其边界的所有点,......
  • 题解 AT3726 [ARC087B] FT Robot
    首先可以观察到一个非常重要的性质:对于一次前进的操作,如果前面有奇数次转向,则走上下,否则走左右。(当然如果一开始就前进就只能走右)于是我们可以将其拆成许多的“块”,并分成两类,即前进方向为左右还是上下。然后对于两个维度分别dp。\(f_{i},_{j}=f_{i-1},_{j-val}\|\f_{i-......