飞!

题解

首先,求逆序数对的思路:
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 ;

}

最新文章

  1. adv
  2. 微信小程序之明源商城系列-01-商城介绍及开发准备
  3. css3 transition
  4. 关于Hibernate 5 和 Hibernate 4 在创建SessionFactory的不同点分析(解决 org.hibernate.MappingException: Unknown entity: xx类报错问题)
  5. DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
  6. Javascript - Arraylike的7种实现
  7. Laravel 5 事件的使用
  8. 设计模式原来如此-代理模式(Proxy Pattern)
  9. 安装nodejs和grunt以后出现 /usr/bin/env: node: No such file or directory
  10. SQL 2005中char、nchar、varchar、ntext and nvarchar(max)的区别
  11. 让Solr返回JSON数据
  12. POJ1087 A Plug for UNIX 【最大流】
  13. JDK与Apache Tomcat服务器的安装步骤
  14. 多线程+socket实现多人聊天室
  15. 第十三课 CSS外观及样式的应用 css学习3
  16. jdk-8u181-docs.chm -- 制作时间2018年8月12日
  17. Ubuntu 12.04上安装MySQL并运行
  18. WSL Windows subsytem linux 的简单学习与使用
  19. 【CF1009F】Dominant Indices(长链剖分)
  20. bootstrap--------bootstrap table

热门文章

  1. apache2不识别php
  2. C++知识点总结(四)——面向对象的编程细节总结
  3. find查找、split分隔、replace替换
  4. show table detail
  5. Python03 字符串类型、强制类型转化、列表、元组、字典、集合
  6. NSClassFromString 实例话静态库中的类
  7. DIY的RPM包怎么签名呢 How to sign your custom RPM package with GPG key
  8. input 输入框两种改变事件的方式
  9. android 应用间共享数据,调用其他app数据资源
  10. Git相关安装包打包下载