Codeforces911D---Inversion Counting

img

题目大意:

给你 n n 个数,和 m 个操作询问,每个询问给你 l,r l , r 两个数,问你反转 l,r l , r 区间的元素后,整个序列的逆序对的个数是奇数个还是偶数个,奇数个输出 odd o d d ,偶数个则输出 even e v e n ,该逆序对以从小到大为标准次序,反转后不会恢复为原序列,且保证 n n 个数中每个数都不相同。

数据范围

1n1500,1m2105,1lirin,1ain;

解题思路:

因为要求每次操作后逆序对的对数的奇偶性,如果想暴力做的话,每次对序列进行反转就是 O(n) O ( n ) 的复杂度,还得重新求总逆序对个数,总复杂度就变为了 O(n2m) O ( n 2 ⋅ m ) ,这显然会 TLE T L E 的,所以得换个想法,我们先求出初始序列的总逆序对个数 res r e s ,根据 [l,r] [ l , r ] 区间逆序对的变化转换为总逆序对个数,但是真正的个数我们其实并不太需要,只需要知道奇偶性就行了;我们知道一个长度为len长的序列,它的逆序对最多为 len(len1)/2 l e n ⋅ ( l e n − 1 ) / 2 (假如该序列为从大到小排序,即总逆序对个数为 ( 1+2+3++(len1)=len(len1)/2 1 + 2 + 3 + ⋯ + ( l e n − 1 ) = l e n ⋅ ( l e n − 1 ) / 2 ) 暂且称为满逆序对,那么现逆序对个数即与满逆序对个数有关,若满逆序对个数为偶数个,那么现逆序对奇偶性与原逆序对相同,即为加减偶数个数,可以用 len(len1)/2 l e n ⋅ ( l e n − 1 ) / 2 代替,否则当满逆序对个数为奇数个时,那么现逆序对奇偶性与原逆序对相反,即为加减奇数个,也可用 len(len1)/2 l e n ⋅ ( l e n − 1 ) / 2 代替,所以每次只需要将 res+=len(len1)/2 r e s + = l e n ⋅ ( l e n − 1 ) / 2 后就可以直接判断奇偶性, O(1) O ( 1 ) 出答案。

AC代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn = 1500;
int n, m, cnt;
int a[maxn + 5];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++) {
        for(int j = i + 1; j <= n; j++)
            if(a[i] > a[j])cnt++;
    }
    scanf("%d", &m);
    for(int i = 1; i <= m; i++) {
        int l, r;
        scanf("%d%d", &l, &r);
        cnt += (r - l + 1) * (r - l) / 2;
        if(cnt & 1)printf("odd\n");
        else printf("even\n");
    }
    return 0;
}

题目链接:Go to!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值