CF911D Inversion Counting

传送门:CF911D Inversion Counting

题意

有一个 nn 个元素的序列,每次操作将区间 [l,r][l,r] 翻转,每次操作后询问序列的逆序对数量。一个序列 aa 的逆序对数量定义为满足 i<ji < jai>aja_i > a_j 的个数。

解法

考虑区间翻转,很容易想到 Splay,但是本题是思维题。

我们先预处理原数组的逆序对数量,那么对于区间 [l,r][l,r],所有数对数量 x=Crl+12=(rl+1)(rl)2x = C_{r-l+1}^{2} = \frac{(r-l+1)*(r-l)}{2},分情况考虑:

  1. xx 是奇数

我们知道数对分为正序对和逆序对,那么很显然正序对个数与逆序对个数不会同奇同偶,即设正序对数量 pp,逆序对数量 yy,那么 p≢y(mod2)p \not \equiv y\pmod 2,翻转区间后整个序列逆序对数量奇偶性相反。

  1. xx 是偶数

设正序对数量 xx,逆序对数量 yy,那么 xy(mod2)x \equiv y\pmod 2,翻转区间后整个序列逆序对数量奇偶性不变。

代码:

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 1505;

int a[N];
int n, m, cnt = 0;

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	scanf("%d", &m);
	for (int i = 1; i <= n; i++)
	{
		for (int j = i + 1; j <= n; j++) cnt += (a[i] > a[j]);
	}
	bool flag = cnt & 1;
	while (m--)
	{
		int l, r;
		scanf("%d %d", &l, &r);
		int k = (r - l + 1) * (r - l) >> 1;
		if (k & 1) flag = !flag;
		printf("%s\n", (flag) ? "odd" : "even");
	}
	return 0;
}
posted @   HappyBobb  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示