首页 > 其他分享 >洛谷 P9843 [ICPC2021 Nanjing R] Paimon Sorting 题解

洛谷 P9843 [ICPC2021 Nanjing R] Paimon Sorting 题解

时间:2024-01-21 17:11:37浏览次数:23  
标签:P9843 ICPC2021 题解 REP 交换 cnt vis res ask

Descirption

给出一个排序算法(用伪代码表示):

SORT(A)
  for i from 1 to n
    for j from 1 to n
      if a[i] < a[j]
        Swap a[i] and a[j]

算出对于一个序列 \(A=a_1,a_2,\cdots,a_n\) 的所有前缀 \(A_k=a_1,a_2,\cdots,a_k\)(\(1\le k\le n\)),\(\operatorname{SORT}(A_k)\) 中的交换(Swap)操作将会被执行几次。

Solution

Part I

考虑对于如何计算整个序列的答案。

先模拟第一次循环,交换该交换的。

观察发现,从第二次循环开始,当外层循环枚举到 \(i\) 时,\([1,i-1]\) 已经排好序了,并且 \(a_{i-1}\) 是全局最大值。此时可能交换的 \(j\) 一定在 \([1,i-1]\) 中,具体地,这次交换会交换 \(\sum_{j=1}^{i-1}[a_j>a_i]\) 次。

因为 \(j<i\),所以 \(i\) 和 \(j\) 交换不会影响之后的次数,树状数组维护 \(\sum_{j=1}^{i-1}[a_j>a_i]\) 即可。

REP(k, 1, n) {
	Fenwick<int> T(n); vector<int> p(n + 1), t(n + 1);
	int cnt = 0; 
	REP(i, 1, k) p[i] = a[i];
	REP(i, 1, k)
		if (p[1] < p[i]) swap(p[1], p[i]), cnt ++;
	REP(i, 1, k) {
		cnt += T.ask(n) - T.ask(p[i]);
		if (!t[p[i]]) T.upd(p[i], 1), t[p[i]] = 1;
	}
	cout << cnt << " \n"[k == n];
}

Part II

考虑在原来算出答案的序列 \(\{a_{n}\}\) 最后加入一个数 \(k\)。

我们设 \(t=\max\{a_{i}\}\)。

如果 \(k\leq t\),那么对第一次循环没有影响,正常二维数点即可。

如果 \(k>t\),那么第一次循环时会把原来在 \(a_1\) 的 \(t\) 放到最后,然后把 \(a_1\) 改成 \(k\)。设原序列中 \(t\) 第二次出现在 \(p\)。对于 \([1,p-1]\) 中的数,把 \(t\) 拿走又加入 \(k\),交换次数不变。对于 \([p,n]\) 中的数,因为前面的 \(t\) 不止一个,加入 \(k\) 后 \(t\) 仍然有贡献,每个位置的交换次数都会加 \(1\)。

简单维护即可。

Fenwick<int> T(n);
vector<int> vis(n + 1);
LL res = 0, p = 0, cnt = 0;
REP(i, 1, n) {
	if (!vis[a[i]]) T.upd(a[i], 1), vis[a[i]] = 1;
	if (i > 1 && a[i] == a[1]) p = 1;
	if (a[1] < a[i])
		res += cnt + 1, cnt = p = 0, swap(a[1], a[i]);
	cnt += p, res += T.ask(n) - T.ask(a[i]);
	cout << res << " \n"[i == n];
}

标签:P9843,ICPC2021,题解,REP,交换,cnt,vis,res,ask
From: https://www.cnblogs.com/Milkcatqwq/p/17978032

相关文章

  • AT_abc337_d 的题解
    AT_abc337_d的题解题目大意给你一个\(H\timesW(H\timesW\leq2\times10^5)\)的矩阵,矩阵由o、x和.构成。存在一种操作:将一个.变成o。问在一段连续的区间内,需要进行多少次操作才可以将同一行或同一列中的连续\(k\)个数都变为o,若无法完成,输出-1。思考过程看......
  • AT_abc337_c的题解
    AT_abc337_c的题解题目大意就是给你一个数组$a=(a_1,a_2,\ldots,a_n)$,若$a_i$为$-1$,那么这个数的下标就是输出序列的开头,否侧,这个数在输出序列中排在$a_i$的下一个。思考过程从样例中不难发现:$1,2,\ldots,n$中的每一个数最多在$a$中出现一次;输出序列中的每一个......
  • P10073 [GDKOI2024 普及组] 刷野 II 的题解
    P10073[GDKOI2024普及组]刷野II的题解谨以此篇题解记录我考场上唯一通过的一题~解题思路可以考虑定义两个指针x和y,分别为左侧攻击到哪里和右侧。此时,从两侧线性想中间递推,若先打左边的代价小就打左边的,否则就打右边的。按照这个方法向中间推就可以了。Code#include<......
  • ABC337 E Bad Juice 题解
    QuestionABC337EBadJuice交互题\(n\)瓶果汁中有\(1\)瓶是坏的,现在需要把这些果汁分给\(m\)个人,每个人可以喝任意瓶,然后通过\(m\)个人的回复判断哪一瓶是坏的需要输出最小的\(m\)以及坏果汁的编号Solution\(m\)返回的结果由\(01\)构成,自然而然想到二进制,考虑......
  • ABC337 D Cheating Gomoku Narabe 题解
    QuestionABC337DCheatingGomokuNarabe给出一个\(H\timesW\)的矩阵,由o,x,.组成,一次操作为把一个.变成o,问需要最少多少次操作使得横着或竖着有连续的\(K\)个oSolution先来考虑只有一行的情况,我们定义一个长度为\(K\)的"窗口",假设需要把这个"窗口"里面的所有......
  • CF526F Pudding Monsters 题解
    题目链接:CF或者洛谷析合树真是连续段问题的降智神器先看下题目的一些特殊性,每行每列恰好有一个棋子。考虑特殊性,\(n\timesn\)的棋盘,那么就该判断是否有\(n\)个棋子,容易观察到,也就是相当于每一行并且每一列都有一个棋子。而容易知道,这些棋子所在的行或者列拿出来应当是“......
  • P4148 简单题 题解
    QuestionP4148简单题有一个\(n\timesn\)的棋盘,每个格子内有一个整数,初始时全部为\(0\),现在需要维护两种操作1xy将格子\(x,y\)里的数字加上\(A\)2x1y1x2y2输出\(x_1,y_1,x_2,y_2\)这个矩形内的数字和强制在线Solution因为强制在线,没法用CDQ什么乱搞,这......
  • P4747 [CERC2017] Intrinsic Interval 题解
    题目链接:IntrinsicInterval讲讲析合树如何解决这种问题,其实这题很接近析合树的板题的应用。增量法进行析合树建树时,需要用ST表预处理出\(max\)和\(min\)以便\(O(1)\)查询极差,然后线段树去维护\([l,r]\)上的极差减区间端点做差即\(diff-(r-l)\),当这玩意等于\(0\)时......
  • P8112 [Cnoi2021] 符文破译 题解
    题目传送门思路先看数据范围,我们发现两个字符串的长度最大会达到\(5\times10^7\)。这立刻打消了我用暴力的想法。于是,我选择了用KMP模式匹配,这一个能够在线性时间内判定字符串\(A\)是否是字符串\(B\)的字串,并求出字符串\(A\)在字符串\(B\)中各次出现的位置。如......
  • HDU2966 In case of failure 题解
    QuestionHDU2966Incaseoffailure给出平面上\(n\)个点坐标,求每个点最近的点的欧几里得距离的平方Solution算是一道K-D树的板子题维度\(K=2\)建立\(K-D\)树,在每一层更新当前最小答案\(now\_ans\),如果在然后继续遍历当前维度下距离\(\le\)的区块随机数据时间复......