zoukankan      html  css  js  c++  java
  • HDU1394(Minimum Inversion Number)

    题目地址:Minimum Inversion Number

    题目大意:

        求逆序对数,求循环移位后逆序数的最小值,意思一次将第一位移到最后一位,然后计算逆序对数,求出最小的那个。

    解题思路:

         因为是序列0->n-1区间的数,所以当你求的,它给出的a1.a2...an-1的逆序对数时cnt,推出如果移位后:设移位a[0],则移位后的逆序对数为 cnt-a[0]+(n-a[i]-1)。知道公式所以先求出给出序列的逆序对,然后从0->n-1移位求出最小的min数即可。

    可以用:线段数、树状数组代码、和归并做。

    线段数:开0->n-1的线段数,然后一次将给出a[i]添加到线段数中,然后计算a[i+1]时就可以对线段数中a[i+1]->n-1区间查找,计算在该区间已经有多少个数已经被添加完成,说明这个数出现在a[i+1]的前面(因为这个区间都大于a[i+1])。

    代码:

      1 #include <algorithm>
      2 #include <iostream>
      3 #include <sstream>
      4 #include <cstdlib>
      5 #include <cstring>
      6 #include <cstdio>
      7 #include <string>
      8 #include <bitset>
      9 #include <vector>
     10 #include <queue>
     11 #include <stack>
     12 #include <cmath>
     13 #include <list>
     14 //#include <map>
     15 #include <set>
     16 using namespace std;
     17 /***************************************/
     18 #define ll long long
     19 #define int64 __int64
     20 #define PI 3.1415927
     21 /***************************************/
     22 const int INF = 0x7f7f7f7f;
     23 const double eps = 1e-8;
     24 const double PIE=acos(-1.0);
     25 const int d1x[]= {0,-1,0,1};
     26 const int d1y[]= {-1,0,1,0};
     27 const int d2x[]= {0,-1,0,1};
     28 const int d2y[]= {1,0,-1,0};
     29 const int fx[]= {-1,-1,-1,0,0,1,1,1};
     30 const int fy[]= {-1,0,1,-1,1,-1,0,1};
     31 const int dirx[]= {-1,1,-2,2,-2,2,-1,1};
     32 const int diry[]= {-2,-2,-1,-1,1,1,2,2};
     33 /*vector <int>map[N];map[a].push_back(b);int len=map[v].size();*/
     34 /***************************************/
     35 void openfile()
     36 {
     37     freopen("data.in","rb",stdin);
     38     freopen("data.out","wb",stdout);
     39 }
     40 priority_queue<int> qi1;
     41 priority_queue<int, vector<int>, greater<int> >qi2;
     42 /**********************华丽丽的分割线,以上为模板部分*****************/
     43 const int M=5010;
     44 struct tree
     45 {
     46     int sum;
     47     int left,right;  //记录区间的左右闭区间坐标
     48 } node[M*4];  //需开四倍的空间大小
     49 int p[M];
     50 int cnt;
     51 void build__tree(int id,int l,int r)  //建树
     52 {
     53     int mid=(l+r)/2;
     54     node[id].left=l;   //初始化赋值区间的坐标
     55     node[id].right=r;
     56     if (l==r)
     57     {
     58         node[id].sum=0;  //初始化区间节点的val值
     59         return ;
     60     }
     61     build__tree(id*2,l,mid);  //左孩子
     62     build__tree(id*2+1,mid+1,r); //右孩子
     63     node[id].sum=node[id*2].sum+node[id*2+1].sum;  //通过递归将各个区间节点val更新
     64 }
     65 int sum(int id,int l,int r)  //区间的更新
     66 {
     67     int mid=(node[id].left+node[id].right)/2;
     68     if (node[id].left==l&&node[id].right==r)
     69         return node[id].sum;
     70     if (l>mid)   //[l,r]在右孩子部分
     71         return sum(id*2+1,l,r);
     72     else if (r<=mid) // [l,r]在左孩子部分
     73         return sum(id*2,l,r);
     74     else  //[l,r]区间,左右孩子都有分别递归。
     75         return sum(id*2,l,mid)+sum(id*2+1,mid+1,r);
     76 }
     77 void updata(int id,int pos,int val)
     78 {
     79     int mid=(node[id].left+node[id].right)/2;
     80     if (node[id].left==pos&&node[id].right==pos)
     81     {
     82         node[id].sum+=val;
     83         return ;
     84     }
     85     if (pos<=mid)
     86         updata(id*2,pos,val);
     87     else
     88         updata(id*2+1,pos,val);
     89     node[id].sum=node[id*2].sum+node[id*2+1].sum;
     90 }
     91 int a[5010];
     92 int main()
     93 {
     94     int n;
     95     while(scanf("%d",&n)!=EOF)
     96     {
     97         int i,j;
     98         int cnt=0;
     99         build__tree(1,0,n-1);
    100         for(i=0; i<n; i++)
    101             scanf("%d",&a[i]);
    102         for(i=0; i<n; i++)
    103         {
    104             cnt+=sum(1,a[i],n-1);
    105             updata(1,a[i],1);
    106         }
    107         int min=cnt;
    108         for(i=0;i<n;i++)
    109         {
    110             cnt-=a[i];
    111             cnt+=n-a[i]-1;
    112             if (cnt<min)
    113                 min=cnt;
    114         }
    115         printf("%d
    ",min);
    116     }
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    Qt多表格滚动条同步
    Trie树
    计算机网络笔记--网络层--ICMP协议
    计算机网络笔记--网络层--NAT
    计算机网络笔记--IP地址
    计算机网络笔记--网络层--ARP协议
    计算机网络笔记--网络层1IP协议
    const与指针
    c/c++笔记--指向数组的指针与二维数组
    机试笔记9--二叉树的遍历
  • 原文地址:https://www.cnblogs.com/ZhaoPengkinghold/p/4009491.html
Copyright © 2011-2022 走看看