飞!

题解

首先,求逆序数对的思路:
1.得到整个数列后,从前往后扫,统计比a[i]小的,在a[i]后面的有多少个
这样做的话,应该是只有n2的暴力作法,没想到更好的方法
2.统计a[i]前面的,且比它大的数
这样做的话,就可以利用输入的时效性,每输入一个数,就把这个数的num[i]值加1,
然后统计比这个数大的数的num和,
因为这里的和一定是在这个数列中比a[i]大,且在它前面出现的数之和,
然后把把这个和加到总逆序数sum里。
这样做的话直接的暴力作法依然是n2,但是,
我们可以在,统计比这个数大的数的num和这一步进行优化,利用线段树求区间域值的复杂度是logn,
所以总体复杂度就降到了nlogn。
 
再来看这道题,求得初始数列的逆序数后,再求其他排列的逆序数有一个规律,就是
sum = sum + (n - 1 - a[i]) - a[i];
这个自行验证吧,相信很容易得出
 
最后,拓展一下,如果要求正序数怎么办?很简单,无非是大小调一下
再问,如果要求满足i<j<k,且a[i]>a[j]>a[k]的数对总数怎么办?
 
可以从中间的这个数入手,统计a[i]>a[j]的对数m,以及a[j]>a[k]的对数n,m*n就是。。。
要求a[i]>a[j]的个数还是一样的,那么a[j]>a[k]的个数呢?
两种思路:
1.得到a[i]>a[j]的对数后,将数列倒过来后再求a[j]<a[k]的对数
2.更简单的做法是,找到规律发现,n = 整个数列中比a[j]小的数 — 在a[j]前面已经出现的比a[j]小的数的个数
即(假设数列是从1开始的) n = (a[j] -1) - (j - 1 - m )
 
如果不理解模拟一边就明白了。
AC代码:
#include <cstdio>

#include <algorithm>

using namespace std;

#define lson l , m , rt << 1

#define rson m + 1 , r , rt << 1 | 1

const int maxn = ;

int sum[maxn<<];

void PushUP(int rt) {

         sum[rt] = sum[rt<<] + sum[rt<<|];

}

void build(int l,int r,int rt) {

         sum[rt] = ;

         if (l == r) return ;

         int m = (l + r) >> ;

         build(lson);

         build(rson);

}

void update(int p,int l,int r,int rt) {

         if (l == r) {

                 sum[rt] ++;

                 return ;

         }

         int m = (l + r) >> ;

         if (p <= m) update(p , lson);

         else update(p , rson);

         PushUP(rt);

}

int query(int L,int R,int l,int r,int rt) {

         if (L <= l && r <= R) {

                 return sum[rt];

         }

         int m = (l + r) >> ;

         int ret = ;

         if (L <= m) ret += query(L , R , lson);

         if (R > m) ret += query(L , R , rson);

         return ret;

}

int x[maxn];

int main() {

         int n;

         while (~scanf("%d",&n)) {

                 build( , n -  , );

                 int sum = ;

                 for (int i =  ; i < n ; i ++) {

                          scanf("%d",&x[i]);

                          sum += query(x[i] , n -  ,  , n -  , );

                          update(x[i] ,  , n -  , );

                 }

                 int ret = sum;

                 for (int i =  ; i < n ; i ++) {

                          sum += n - x[i] - x[i] - ;

                          ret = min(ret , sum);

                 }

                 printf("%d\n",ret);

         }

         return ;

}

hdu Minimum Inversion Number(逆序数的小知识与线段树)的更多相关文章

  1. hdu 1394 Minimum Inversion Number(逆序数对) : 树状数组 O(nlogn)

    http://acm.hdu.edu.cn/showproblem.php?pid=1394  //hdu 题目   Problem Description The inversion number ...

  2. hdu 1394 Minimum Inversion Number 逆序数/树状数组

    Minimum Inversion Number Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showprob ...

  3. HDU-1394 Minimum Inversion Number (逆序数,线段树或树状数组)

    The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that ...

  4. HDU 4911 Inversion (逆序数 归并排序)

    Inversion 题目链接: http://acm.hust.edu.cn/vjudge/contest/121349#problem/A Description bobo has a sequen ...

  5. ZYB's Premutation(有逆序数输出原序列,线段树)

    ZYB's Premutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Othe ...

  6. HDU 1394 Minimum Inversion Number(线段树的单点更新)

    点我看题目 题意 :给你一个数列,a1,a2,a3,a4.......an,然后可以求出逆序数,再把a1放到an后,可以得到一个新的逆序数,再把a2放到a1后边,,,,,,,依次下去,输出最小的那个逆 ...

  7. HDU 1394 Minimum Inversion Number(线段树/树状数组求逆序数)

    Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...

  8. HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number                         ...

  9. HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)

    题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS     Memory Limit: 32768 K Description The inve ...

随机推荐

  1. 有关less 处理@arguments的一些高级技巧

    //http://stackoverflow.com/questions/14350749/less-arguments-with-linear-gradients-commas .mixin(... ...

  2. MVC分层思想、SSM编程架构

    1 MVC 和 SSM

  3. Executor线程池

    Executor线程池框架: 使用线程池的优点: 1.重用存在的线程 2.减少对象创建.消亡的开销 3.性能佳 4.可有效控制最大并发线程数,提高系统资源的使用率 5.避免过多资源竞争,避免堵塞 6. ...

  4. 算法Sedgewick第四版-第1章基础-007一用两个栈实现简单的编译器

    1. package algorithms.util; import algorithms.ADT.Stack; /****************************************** ...

  5. cakephp数据库配置

  6. AbstractBootstrap的研读

    AbstractBootstrap是一个工具类,用来配置和启动Channel的,下面看下AbstractBootstrap的类继承,ServerBootstrap用于启动ServerChannel的, ...

  7. HtmlAgilityPack HTML操作类库的使用

    HtmlAgilityPack是.NET下的一个开源的HTML解析类库.支持用XPath来解析HTML.命名空间:HtmlAgilityPack. 1.读取网络中html网页内容,获取网页中元素bod ...

  8. C# 实现文件(夹)在ftp服务器间的同步【无需将文件(夹)保存到本地】

    C#实现不同ftp服务器间文件(夹)同步 图1 实现不同ftp服务器间文件(夹)同步的实现思路图 /// <summary> /// 将文件夹1从ftp服务器1移到ftp服务器2文件夹2 ...

  9. MVC中使用代码创建数据库(code first +mysql+EF)

    1.新建一个mvc项目 2.安装mysql需要的几个文件 EntityFramework.MySql.Data(6.9.12)和MySql.Data.Entity (6.9.12) 这里有几点要注意 ...

  10. jQuery+css实现tab功能

    点击我我会消失 Click me 点击按钮我会消失,再点击我会出现 演示tab tab1 tab2 tab3 [环球时报记者 郭芳] “中国秘密发射新快速响应火箭”,25日,在中国官方媒体报道我国“快 ...