题解 CF911D 【Inversion Counting】
蒟蒻的第一篇题解,对大佬来说可能有点啰嗦
首先我们要仔细看题,要求的是[L, R]翻转后整个序列中逆序对的奇偶性,不是[L, R]中逆序对的奇偶性,也不是逆序对的总数
接着我们就可以思考[L, R]中的逆序对与整个序列逆序对的关系,我们会惊奇地发现,由于[L, R]中的数翻转之后与[L, R]区间之外的数的相对位置并不会发生改变,所以除了
那如何求出这个变化呢? 思考一下逆序对的定义:
对于给定的一段正整数序列,逆序对就是序列中
a_i>a_j 且i<j 的有序对 ——P1908 逆序对
接下来是本道题的主要难点:
对于任意数对
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int m, x, y, num;
int read() {
int x = 0; char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
return x;
}
#define lowbit(x) x&-x
int n, a[600000], b[600000], c[600000];
void add(int x) {
for(int i = x; i <= n; i += lowbit(i)) ++c[i];
}
long long sum(int x) {
long long ans = 0;
for(int i = x; i; i -= lowbit(i)) ans += c[i];
return ans;
}
int main(void) {
long long ans = 0;
cin >> n;
for(int i = 1; i <= n; ++i) a[i] = b[i] = read();
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; ++i) a[i] = n - (lower_bound(b + 1, b + n + 1, a[i]) - b) + 1;
for(int i = 1; i <= n; ++i) {
ans += sum(a[i] - 1);
add(a[i]);
}
//上面是树状数组求逆序对个数,这题归并甚至暴力求逆序对因该也是可以的
ans &= 1;
m = read();
while(m--)
{
x = read();
y = read();
num = y-x+1;
num = num*(num-1)/2;//求数对总数
if((num)&1) ans = (ans+1)&1;//判断奇偶性是否改变
if(ans) puts("odd");
else puts("even");
}
}