zoukankan      html  css  js  c++  java
  • 线段树 逆序对 Minimum Inversion Number HDU

    Minimum Inversion Number

     HDU - 1394 

    求最小反转数,就是求最少的逆序对。

    逆序对怎么求,就是先把所有的数都初始化为0,然后按照顺序放入数字,放入数字前查询从这个数往后面的数的位置是不是被占了,被占了说明有逆序对。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <algorithm>
    #define debug(n) printf("%d
    ",n)
    #define inf 0x3f3f3f3f;
    using namespace std;
    const int maxn = 5000 + 10;
    int n, a[maxn];
    struct node
    {
        int l, r, num;
    }tree[4*maxn];
    
    void push_up(int id)
    {
        tree[id].num = tree[id << 1].num + tree[id << 1 | 1].num;
    }
    
    void build(int id, int l, int r)
    {
        tree[id].l = l;
        tree[id].r = r;
        if (l == r)
        {
            tree[id].num = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        push_up(id);
    }
    
    int query(int x, int y, int id)
    {
        int l = tree[id].l;
        int r = tree[id].r;
        if (x <= l && y >= r)
        {
            return tree[id].num;
        }
        int mid = (l + r) >> 1;
        int ans = 0;
        if (x <= mid) ans += query(x, y, id << 1);
        if (y > mid) ans += query(x, y, id << 1 | 1);
        push_up(id);
        return ans;
    }
    
    void update(int x, int y, int id)
    {
        int l = tree[id].l;
        int r = tree[id].r;
        if (x <= l && y >= r)
        {
            tree[id].num = 1;
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) update(x, y, id << 1);
        if (y > mid) update(x, y, id << 1 | 1);
        push_up(id);
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF)
        {
            int sum = 0,ans=inf;
            build(1, 0, n - 1);
            for (int i = 0;i < n;i++)
            {
                
                scanf("%d", &a[i]);
                sum += query(a[i], n - 1, 1);
                update(a[i], a[i], 1);
                //debug(sum);
            }
            //debug(sum);
            for (int i = 0;i < n;i++)
            {
                sum = sum + (n - 1 - a[i]) - a[i];
                ans = min(sum, ans);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    View Code

    Laptop

    对其中一个进行排序,转化成逆序对。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <iostream>
    #include <map>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 2e5 + 10;
    typedef long long ll;
    map<ll, ll>mp;
    struct node
    {
        int l, r;
        int sum;
    }tree[4*maxn];
    pair<ll, ll>a[maxn];
    bool cmp(pair<ll,ll>a,pair<ll,ll>b)
    {
        return a.first > b.first;
    }
    bool cmp1(pair<ll,ll>a,pair<ll,ll>b)
    {
        return a.second < b.second;
    }
    void build(int id, int l, int r) {
        tree[id].l = l;
        tree[id].r = r;
        if (l == r) {
            tree[id].sum = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
    }
    
    int query(int id,int x,int y)
    {
        int l = tree[id].l;
        int r = tree[id].r;
        if(x<=l&&y>=r)
        {
        //    printf("id=%d sum=%d 
    ", id,tree[id].sum);
            return tree[id].sum;
        }
        int ans = 0;
        int mid = (l + r) >> 1;
        if (x <= mid) ans += query(id << 1, x, y);
        if (y > mid) ans += query(id << 1 | 1, x, y);
    //    printf("id=%d ans=%d l=%d r=%d x=%d y=%d 
    ", id, ans, l, r,x,y);
        return ans;
    }
    
    void push_up(int id)
    {
        tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum;
    }
    
    void update(int id,int x)
    {
        int l = tree[id].l;
        int r = tree[id].r;
        if(l==r)
        {
            tree[id].sum = 1;
            return;
        }
        int mid = (l + r) >> 1;
        if (x <= mid) update(id << 1, x);
        else update(id << 1 | 1, x);
        push_up(id);
    }
    
    
    int main()
    {
        int n, tot = 0;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%lld%lld", &a[i].first, &a[i].second);
        sort(a + 1, a + 1 + n, cmp1);
        for(int i=1;i<=n;i++)
        {
            if (mp[a[i].second]) continue;
            mp[a[i].second] = ++tot;
        }
        sort(a + 1, a + 1 + n, cmp);
        build(1, 1, tot);
        int ans = 0;
        for(int i=1;i<=n;i++)
        {
            if (query(1, mp[a[i].second], tot)) ans++;
            update(1, mp[a[i].second]);
        }
        printf("%d
    ", ans);
        return 0;
    }
    /*
     6
    100 100
    90 100
    90 100
    80 90
    80 90
    70 100
     */
    View Code

    还有一个是选拔赛的题目,学校oj崩了,下次再写。

  • 相关阅读:
    如何从程序集中加载及卸载插件(下)
    Castle AOP 系列(四):实现一个简单的基于上下文调用的权限校验机制
    Castle AOP 系列(一):对类方法调用的拦截
    Mussel使用系列(六):分布式调用的牛刀小试
    新发现XmlNode中变态的地方
    我们发现你在XX邮箱的账号密码与其他网站被盗账号密码一致 请立即更改密码。
    html5 css3 新特性一览表
    [android] Http Post 请求
    [vs 使用技巧] VS2013显示行数 行号
    ORACLE数据库存储使用情况查询命令
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11199972.html
Copyright © 2011-2022 走看看