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崩了,下次再写。

  • 相关阅读:
    eclipse下c/cpp " undefined reference to " or "launch failed binary not found"问题
    blockdev 设置文件预读大小
    宝宝语录
    CentOS修改主机名(hostname)
    subprocess报No such file or directory
    用ldap方式访问AD域的的错误解释
    英特尔的VTd技术是什么?
    This virtual machine requires the VMware keyboard support driver which is not installed
    Linux内核的文件预读详细详解
    UNP总结 Chapter 26~29 线程、IP选项、原始套接字、数据链路访问
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11199972.html
Copyright © 2011-2022 走看看