[CF785E]Anton and Permutation

Posted memory-of-winter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF785E]Anton and Permutation相关的知识,希望对你有一定的参考价值。

题目大意:有一串数为$1sim n(nleqslant2 imes10^5)$,$m(mleqslant5 imes10^4)$次询问,每次问交换位置为$l,r$的两个数后数列中逆序对的个数。

题解:发现交换位置为$l,r$的数后,逆序对的变化只和区间$(l,r)$内的数与$s_l,s_r$的大小关系有关,设$S_i$表示区间$(l,r)$中比$s_i$小的数,$B_i$表示区间$(l,r)$中比$s_i$大的数,$ans‘=ans+S_r-B_r-S_l+B_l$。设$len=r-l-1$,$ans‘=ans+S_r-(len-S_r)-S_l+(len-S_l)=ans+2(S_r-S_l)$。

考虑分块,设块大小为$S$,在块内排序,在边角处暴力,在整块处二分查找位置,询问的复杂度是$O(2S+dfrac n Slog_2S)$;修改为二分处位置直接插入或删除,复杂度$O(4S)$,所以当$S$略大于$sqrt n$时最优。(反正我懒得算,随便猜一个)

卡点:

  1. 计算$2(S_r-S_l)$时使用了位运算,当$S_r-S_l$为负数时出锅
  2. 最开始块大小设成了$512$,计算块时用了$2^8$

 

C++ Code:

#include <algorithm>
#include <cstdio>
#include <vector>
#define maxn 200010
const int BSZ = 1000, BNUM = maxn / BSZ + 10;

int n, m;
long long ans;
int L[BNUM], R[BNUM], bel[maxn], s[maxn];
std::vector<int> V[BNUM];

int query(int l, int r, int x) {
	if (l > r) return 0;
	const int lb = bel[l], rb = bel[r];
	int res = 0;
	if (lb == rb) for (int i = l; i <= r; ++i) res += s[i] < x;
	else {
		for (int i = l; i <= R[lb]; ++i) res += s[i] < x;
		for (int i = lb + 1; i < rb; ++i) res += std::upper_bound(V[i].begin(), V[i].end(), x) - V[i].begin();
		for (int i = L[rb]; i <= r; ++i) res += s[i] < x;
	}
	return res;
}

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; ++i) V[bel[i] = i / BSZ + 1].push_back(s[i] = i);
	const int B = bel[n];
	for (int i = 1; i <= B; ++i) {
		L[i] = (i - 1) * BSZ;
		R[i] = L[i] + BSZ - 1;
	}
	L[1] = 1, R[B] = n;
	while (m --> 0) {
		int l, r;
		scanf("%d%d", &l, &r);
		if (l == r) {
			printf("%lld
", ans);
			continue;
		}
		if (l > r) std::swap(l, r);
		const int lb = bel[l], rb = bel[r];

		ans += (query(l + 1, r - 1, s[r]) - query(l + 1, r - 1, s[l])) * 2;
		ans += (s[l] < s[r]) ? 1 : -1;
		printf("%lld
", ans);

		if (lb != rb) {
			V[lb].erase(std::lower_bound(V[lb].begin(), V[lb].end(), s[l]));
			V[lb].insert(std::upper_bound(V[lb].begin(), V[lb].end(), s[r]), s[r]);
			V[rb].erase(std::lower_bound(V[rb].begin(), V[rb].end(), s[r]));
			V[rb].insert(std::upper_bound(V[rb].begin(), V[rb].end(), s[l]), s[l]);
		}
		std::swap(s[l], s[r]);
	}
	return 0;
}

  

以上是关于[CF785E]Anton and Permutation的主要内容,如果未能解决你的问题,请参考以下文章

题解 CF785E Anton and Permutation

codeforces785E Anton and Permutation

CodeForces 785E Anton and Permutation

题解 CF785A Anton and Polyhedrons

题解 CF734F Anton and School

CF785D Anton and School - 2