AT4363 [ARC102D] Revenge of BBuBBBlesort

https://www.luogu.com.cn/problem/AT4363

发现奇数位和偶数位的逆序对个数互不影响

  • 奇数位上的数一定不会换到偶数位上
  • 每次交换,只会让奇数位或偶数位其中一个的逆序对个数-1,让总逆序对数-3

所以 总 逆 序 对 个 数 = 3 ( 奇 数 位 逆 序 对 个 数 + 偶 数 位 逆 序 对 个 数 ) 总逆序对个数=3(奇数位逆序对个数+偶数位逆序对个数) =3(+)
然后不难证明这是充要的
代码求3遍逆序对即可

code:


#include<bits/stdc++.h>
#define ll long long
#define N 300050
#define lowbit(x) (x & -x)
using namespace std;
int t[N], n, a[N];
void update(int x, int y) {
    for(; x <= n; x += lowbit(x)) t[x] += y;
}
int query(int x) {
    int ret = 0;
    for(; x; x -= lowbit(x)) ret += t[x];
    return ret;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);

    for(int i = 1; i <= n; i ++) if((a[i] & 1) != (i & 1)) {
        printf("No"); return 0;
    }
    ll s0 = 0, s1 = 0, s2 = 0;
    for(int i = 1; i <= n; i ++) {
        update(a[i], 1);
        s2 += i - query(a[i]);
    }
    
    for(int i = 0; i <= n; i ++) t[i] = 0;
    for(int i = 1; i <= n; i += 2) {
        update(a[i], 1);
        s1 += (i + 1) / 2 - query(a[i]);
    }
    
    for(int i = 0; i <= n; i ++) t[i] = 0;
    for(int i = 2; i <= n; i += 2) {
        update(a[i], 1);
        s0 += i / 2 - query(a[i]);
    }
    if(3 * (s0 + s1) == s2) printf("Yes");
    else printf("No");
    return 0;
}
posted @ 2021-10-29 09:12  lahlah  阅读(34)  评论(0编辑  收藏  举报