栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

P1908 逆序对 ——树状数组求逆序对模板

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

P1908 逆序对 ——树状数组求逆序对模板

​​​​​​P1908

求逆序对,注意可能有重复数字,排序的时候要注意,否则会wa

C[x]表示1-x中已经有的数字数量,也就是说如果1-5中有3个数,那么逆序就是5-3=2,但是正序是C[x-1] = C[4] = 2

数组C中存的是正序对-1,所以每次操作要sum += i - sum(node[i].index),这样才是逆序对

时间复杂度O(nlogn)

// Decline is inevitable,
// Romance will last forever.
// P1908
//#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define mst(a, x) memset(a, x, sizeof(a))
#define INF 0x3f3f3f3f
//#define mp make_pair
#define pii pair
#define fi first
#define se second
#define ll long long
//#define int long long
const int maxn = 5e5 + 10;
const int maxm = 25;
const int P = 1e9 + 7;
int C[maxn], n, m;
struct Node {
    int v, index;
    bool operator <(const Node &x) const {
        if(v == x.v) return index < x.index;    //有重复数字则不能省略这句话
        return v < x.v;
    }
}node[maxn];
int lb(int x) {
    return x & -x;
}
int sum(int x) {    //前x组的和
    int ret = 0;
    while(x) {
        ret += C[x];
        x -= lb(x);
    }
    return ret;
}
void add(int x, int d) {    //第x组加d
    while(x <= n) {
        C[x] += d;
        x += lb(x);
    }
}
int t = 0;
void solve() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        int a;
        scanf("%d", &a);
        node[i].index = i;
        node[i].v = a;
    }
    sort(node + 1, node + n + 1);
    ll ans = 0;
    for(int i = 1; i <= n; i++) {
        add(node[i].index, 1);
        ans += i - sum(node[i].index);
    }
    printf("%lldn", ans);
}
signed main() {
//    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//    int T; scanf("%d", &T); while(T--)
//    int T; cin >> T; while(T--)
    solve();
    return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/291662.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号