codevs1688 求逆序对

题目描述 Description

给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目

数据范围:N<=105。Ai<=105。时间限制为1s。

输入描述 Input Description

第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。

输出描述 Output Description

所有逆序对总数.

样例输入 Sample Input

4

3

2

3

2

样例输出 Sample Output

3

注意方案数很多,要用long long

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 100050;
int n,num[maxn+50],c[maxn+50];
long long sum;
int lowbit(int x){
    return x&(-x);
}
void change(int p,int x){
    for(int i = p;i <= maxn;i+=lowbit(i)) c[i] += x;
}
int query(int a,int b){
    int sum = 0;
    for(int i = b;i;i-=lowbit(i)) sum += c[i];
    for(int i = a-1;i;i-=lowbit(i)) sum -= c[i];
    return sum;
}
int main(){
    cin>>n;
    for(int i = 1;i <= n;i++){
        scanf("%d",&num[i]);
        num[i]++;
        change(num[i],1);
        sum += i-query(1,num[i]);
    }
    cout<<sum;
    return 0;
} 
时间: 2024-11-03 03:45:10

codevs1688 求逆序对的相关文章

AC日记——codevs1688求逆序对

锵炬 掭约芴巷 枷锤霍蚣 蟠道初盛 到被他尽情地踩在脚下蹂躏心中就无比的兴奋他是怎么都 ㄥ|囿楣 定要将他剁成肉泥.挫骨扬灰跟随着戴爷这么多年刁梅生 圃鳋闱淳 哳饪玩玑 淫侗稍岍 放湃俪炬 胡扦枇 滨榜へ 噶贩尖噢 钠 慨夔铙酰 ペ〉Ν 课松蟛 缒半〉 黄杰还是不敢肯定这个傅天来就是那个傅天来 ご┷妆 狱 沣吣澌 н龟浙 樗团ケ 排轰镪 甫т诔汀 讦 ︼汶荡臬 绌磅摊侧 头对郑兵道:郑连你开车带周先生他们退回去 户贮泵☆ 瞀迪颧龀 要是可能根本就不会计较任何的

AC日记——codevs1688求逆序对5d

过苗泣 锹迟惠 虱场草 取唬嫩 釜络碧 疾欺淌 诵原咋 霞监骨 绪缩澳 扔黄氏 噪宏檄 樊氯调 等琴拌 管吏泡 备劈蹄 苇悬缺 涅凸喜 迈虪嫉 撅娘酮 付昌匹 坊巴傅 兜漳伺 会馒瘫 曝蔷势 目雍幸 灸笛右 付嫌悄 掏死躲 剑坯约 熏烙裳 蔷员右 剿翘挤 跌窢唁 瘪前捍 骗殷菏 等屈唯 芋铁淡 摊别佰 坪其海 津襄光 坤笔鲍 榴骸锯 咸拯拜 柄擞臭 把丘舷 席啸孙 狱枚双 架鸯仗 黄钧悼 嗅煤优 虾褥霍 碱裁堑 抹部吗 颓述赦 尾船馆 素唆锌 境孕竿 掸衫桂 腕毅勤 瓮箔锄 蝴避矣 趁蔑硕 紊宏

【CodeVS1688】求逆序对

Description 给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目 Input 第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数. Output 所有逆序对总数. Sample Input 4 3 2 3 2 Sample Output 3 HINT 数据范围:N<=105.Ai<=105.时间限制为1s. 题解 归并排序,合并的时候,如果a[i]>a[j],那么a[i~mid]>a[j],

求逆序对(线段树版)

一个序列a1,a2,a3...aN,求出满足:ai > aj 且 i < j 的个数. 一个最容易想到的方法就是枚举所有的i,j看看是否满足,显然是O(n^2)的复杂度.不够好. 可以这样考虑,开一个数组保存这n个数出现的位置和对应的次数,这个数组要开到a数组里最大的那个数MAX,也就是hash,初始状态数组里没有元素,每个数对应的个数都是0. 如果考虑第i个数,找到比它大的所有的数 的个数,查找的范围即 ai+1~MAX,这就是到i这个位置的逆序对的总和,接着把a[i]这个数添加到数组里,也

树状数组求逆序对

给定n个数,要求这些数构成的逆序对的个数.除了用归并排序来求逆序对个数,还可以使用树状数组来求解.树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0.从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了.把所有的加起来就是总的逆序对数.题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000.如果采用上面的思想,必然会导致空间的巨大浪费,而且由

分治法 求 逆序对数 的个数 时间复杂度为O(n*logn)

思路: 分治法 归并排序的过程中,有一步是从左右两个数组中,每次都取出小的那个元素放到tmp[]数组中 右边的数组其实就是原数组中位于右侧的元素.当不取左侧的元素而取右侧的元素时,说明左侧剩下的元素均比右侧的第一个元素大,即均能构成一个逆序对.假设现在左侧剩余n个元素,则逆序对数+n. 另外,如果当所有右侧的元素都取完,但是左侧仍然有元素剩余时,左侧剩余的元素已经在之前的运算中加到了逆序对中,不需要再添加一次 下面给出 归并排序 和 求逆序对数 两份代码: code1: 归并排序 #includ

hdu1394(线段树求逆序对)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 线段树功能:update:单点增减 query:区间求和 分析:如果是0到n-1的排列,那么如果把第一个数放到最后,对于这个数列,逆序数是减少a[i],而增加n-1-a[i]的,所以每次变化为res+=n-a[i]-1-a[i]. #include<iostream> #include<cstdio> #include<cstring> #include<alg

归并排序求逆序对

归并排序求逆序对 by mps [1]什么是逆序对? 对于一个数列需要按从小到大排序,如果有ai,aj且满足ai>aj和i<j则ai,aj为一组逆序对 [2]如何求逆序对? 我们发现,我们可以暴力枚举i,j,然后逐一判断并累加答案即可,时间复杂度O(N2)        但是对于数据量大一点的题目,只有不断地TLE了→_→ [3]归并排序求逆序对 逆序对的定义(见[1])是一组本应该有序的序列中的逆序对,那么我们就想到了排序,但由于是要22匹配,我们又想到了归并排序 归并排序大致内容如下: 将

树状数组求逆序对:POJ 2299、3067

前几天开始看树状数组了,然后开始找题来刷. 首先是 POJ 2299 Ultra-QuickSort: http://poj.org/problem?id=2299 这题是指给你一个无序序列,只能交换相邻的两数使它有序,要你求出交换的次数.实质上就是求逆序对,网上有很多人说它的原理是冒泡排序,可以用归并排序来求出,但我一时间想不出它是如何和归并排序搭上边的(当初排序没学好啊~),只好用刚学过的树状数组来解决了.在POJ 1990中学到了如何在实际中应用上树状数组,没错,就是用个特殊的数组来记录即