本题求逆序对的思路还是按照归并排序的过程去求解,但不同之处在于本题需要不断的变换区间里面数的排列。首先考虑在每一次变换之后都去求解逆序对的数量肯定是会超时的。
然后可以联想到如果在区间发生变化之后快速求出逆序对的个数,即可发现在一个区间里面翻转之后逆序对的个数=区间里面的对数-翻转之前逆序对的个数。
可以列出公式:ans-(r-l+1)*(r-l)/2-2x(ans是逆序对的总个数,x是反转之前区间里面逆序对的个数)。可知2x必然是偶数,那么ans奇偶性的变化就取决于(r-l+1)*(r-l)/2,
解到这里就可以发现每一个奇偶性的变化仅仅取决于(r-l+1)*(r-l)/2的奇偶性。这样就可以不必要从新去求逆序对的个数。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 1e5+10;
int a[maxn];
int temp[maxn];
ll cnt = 0;
int read() {
int num = 0, k = 1;
char c = getchar();
while (!(c=='-'||(c>='0'&&c<='9'))) {
c = getchar();
}
while (c=='-') {
k = -k;
c = getchar();
}
while (c>='0'&&c<='9') {
num = num*10 + (c-'0');
c = getchar();
}
return num*k;
}
void Merge(int l1, int r1, int l2, int r2)
{
memset(temp, 0, sizeof(temp));
int n = 0, begin = l1;
while (l1<=r1&&l2<=r2) {
if (a[l1]<=a[l2]) temp[n++] = a[l1++];
else {
temp[n++] = a[l2++];
cnt += r1-l1+1;
}
}
while (l1<=r1) temp[n++] = a[l1++];
while (l2<=r2) temp[n++] = a[l2++];
for (int i=0;i<n;i++) {
a[begin+i] = temp[i];
}
}
void find_inv_num(int l, int r)
{
if (l==r) return ;
int mid = (l+r)/2;
find_inv_num(l, mid);
find_inv_num(mid+1, r);
Merge(l, mid, mid+1, r);
}
int main() {
int n;
scanf("%d", &n);
for (int i=1;i<=n;i++) {
a[i] = read();
}
find_inv_num(1, n);
int p;
if (cnt%2==0) p = 1;
else p = 0;
int m;
int l, r;
scanf("%d", &m);
while (m--) {
l = read();r=read();
int jio = (r-l+1)*(r-l)/2;
if (jio&1==1) {
p = p^1;
}
if (p) {
printf("like\n");
} else {
printf("dislike\n");
}
}
return 0;
}

京公网安备 11010502036488号