C. Insertion Sort

Petya is a beginner programmer. He has already mastered the basics of the C++ language and moved on to learning algorithms. The first algorithm he encountered was insertion sort. Petya has already written the code that implements this algorithm and sorts the given integer zero-indexed array a of size n in the non-decreasing order.

for (int i = 1; i < n; i = i + 1)
{
int j = i;
while (j > 0 && a[j] < a[j - 1])
{
swap(a[j], a[j - 1]); // swap elements a[j] and a[j - 1]
j = j - 1;
}
}

Petya uses this algorithm only for sorting of arrays that are permutations of numbers from 0 to n - 1. He has already chosen the permutation he wants to sort but he first decided to swap some two of its elements. Petya wants to choose these elements in such a way that the number of times the sorting executes function swap, was minimum. Help Petya find out the number of ways in which he can make the swap and fulfill this requirement.

It is guaranteed that it's always possible to swap two elements of the input permutation in such a way that the number of swap function calls decreases.

Input

The first line contains a single integer n (2 ≤ n ≤ 5000) — the length of the permutation. The second line contains n different integers from 0 to n - 1, inclusive — the actual permutation.

Output

Print two integers: the minimum number of times the swap function is executed and the number of such pairs (i, j) that swapping the elements of the input permutation with indexes i and j leads to the minimum number of the executions.

Examples
input
5
4 0 3 1 2
output
3 2
input
5
1 2 3 4 0
output

 
3 4
Note

In the first sample the appropriate pairs are (0, 3) and (0, 4).

In the second sample the appropriate pairs are (0, 4), (1, 4), (2, 4) and (3, 4).

题意:给出n个数,范围0到n-1,然后给出一个插入排序的代码,可以交换两个数,然后使交换后的排列使用交换函数的次数最少,然后问交换后的排列的调用交换函数最少次数是多少

和能有几个索引对交换可以的到最少

思路:首先它的范围只有5000,然后我们看到那个插入排序想想,他只有前面大于后面的就要交换一次,所以没交换的时候的次数其实就是整个排列的逆序数,然后我们其实考虑的就是

交换一个索引使得他的逆序对个数减少最多,然后求有几个这样的索引即可,逆序数这部分我们可以使用树状数组求,我们枚举每个索引,只有前面这个数大于后面的时候我们才要考虑

是否要交换

给出一个例子

4 5 0 2 3 7 1

然后我们当前访问的索引对是(0, 7)-〉4 1

然后我们如何计算4 1交换后能减少多少个逆序对呢

首先我们如果交换 4 1的话 中间那些比4大的数的逆序对肯定不会改变,因为这些数都是大于4的,我把1 4交换,4还是小于那些数,这些逆序对就不会改变了

小于1的数也不用考虑,因为例子中的4 1交换,中间那个0还是小于1,逆序对还是存在,所以并 没有改变

所以我们只要考虑那些小于4大于1的数(a[j]<x<a[i])

我们用树状数组来优化处理

把中间小于4的数都入树状数组

然后是1的时候,我们找出大于1的数有多少然后我们可以找到2 3这两个数

然后我们把4 和1交换之后,中间那些小于4大于1的数因为大于他们的4到了后面,他们的逆序对都-1,还有1移到了2 3这些数前面,所以又要减去这么多逆序对数

总的就是   a[j]<x<a[i] 的两倍

#include<cstdio>
#include<cstring>
using namespace std;
int n,a[];
int f[];
int lowbit(int x)
{
return x&(-x);
}
int add(int x)
{
while(x)
{
f[x]++;
x-=lowbit(x);
}
}
int query(int x)
{
int sum=;
while(x<=n)
{
sum+=f[x];
x+=lowbit(x);
}
return sum;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
a[i]++;
}
int s=;
int mx=,cs=;
for(int i=;i<=n;i++)
{
memset(f,,sizeof(f)); //把之前树状数组的数清空
for(int j=i+;j<=n;j++)
{
if(a[i]>a[j])
{
s++;//存的是总的逆序对个数
int num=+*query(a[j]);//求得能减去的逆序对个数,+1是因为当前还没有入树状数组
if(num>mx)//大于更新
{
mx=num;
cs=;
}
else if(num==mx) //等于得时候说明索引对又新加了一对
{
cs++;
}
add(a[j]);
}
}
}
printf("%d %d",s-mx,cs);
}

Codeforces Round #212 (Div. 2) C. Insertion Sort的更多相关文章

  1. 贪心/数学 Codeforces Round #212 (Div. 2) A. Two Semiknights Meet

    题目传送门 /* 贪心/数学:还以为是BFS,其实x1 + 4 * k = x2, y1 + 4 * l = y2 */ #include <cstdio> #include <al ...

  2. Codeforces Round #486 (Div. 3)-B. Substrings Sort

    B. Substrings Sort time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  3. Codeforces Round #648 (Div. 2) B. Trouble Sort

    一开始读错题了...想当然地认为只能相邻元素交换...(然后换了两种写法WA了4发,5分钟切A的优势荡然无存) 题目链接:https://codeforces.com/contest/1365/pro ...

  4. Codeforces Round #198 (Div. 2) D. Bubble Sort Graph (转化为最长非降子序列)

    D. Bubble Sort Graph time limit per test 1 second memory limit per test 256 megabytes input standard ...

  5. Codeforces Round #650 (Div. 3) F1. Flying Sort (Easy Version) (离散化,贪心)

    题意:有一组数,每次操作可以将某个数移到头部或者尾部,问最少操作多少次使得这组数非递减. 题解:先离散化将每个数映射为排序后所对应的位置,然后贪心,求最长连续子序列的长度,那么最少的操作次数一定为\( ...

  6. Codeforces Round #212 (Div. 2) D. Fools and Foolproof Roads 并查集+优先队列

    D. Fools and Foolproof Roads   You must have heard all about the Foolland on your Geography lessons. ...

  7. Codeforces Round 212 Div 2 报告(以前没写完,现在也没心情补了,先就这样吧)

    A. Two Semiknights Meet 题目大意:有一个8x8的棋盘,上面放有两个骑士,骑士以“田字”的方式走.每个方格都被定义为good或者bad,问骑士能否在good的格子中相遇? 由于骑 ...

  8. Codeforces Round #258 (Div. 2) 小结

    A. Game With Sticks (451A) 水题一道,事实上无论你选取哪一个交叉点,结果都是行数列数都减一,那如今就是谁先减到行.列有一个为0,那么谁就赢了.因为Akshat先选,因此假设行 ...

  9. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

随机推荐

  1. Jenkins与Gitlab集成

    一.安装jenkinshttps://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/     #清华yum源 yum -y install java-1.8. ...

  2. LeetCode--350--两个数组的交集2

    问题描述: 给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = ...

  3. vue动画

    最近想搞搞vue的过渡和动画,以为照着官网写就好了,谁知道还是出现一些状况 具体表现就是不用webpack打包时候写的过渡是正常的,而用了webpack打包就不正常了 说使用了未定义的element: ...

  4. inflate()引发NullPointerException

    有时候我们在infalete的时候明明什么都对为什么它会提示出错 原意是你的资源layout出错了 注意看有没有把View写成view 这个View应该大写!V而不是小写v 踩坑踩了两次了!上次以为是 ...

  5. source code spark

    http://blog.csdn.net/pelick/article/category/1556747 http://www.cnblogs.com/hseagle/

  6. stock 基本操作

    追涨停   量比 大于5      0%-2%   个股    2点卖     37分钟买   板块5 -8 只涨停    板块分向标   追踪短期个股的涨跌现象    明白市场大级别趋势     主 ...

  7. 什么是V模型?使用SDLC和STLC学习案例研究

    本教程详细介绍了软件/系统开发生命周期(SDLC),如瀑布循环和迭代循环,如RAID和Agile.此外,它继续解释测试的V模型和STLC(软件测试生命周期). 假设为您分配了一项任务,即为客户开发自定 ...

  8. 论raw_input与input之间的缠缠绵绵

    例子1:py2.7中,raw_input输入整数,返回的是str. input1=raw_input("raw_input:") print(type(input1)) print ...

  9. bzoj-2038-莫队

    2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 15784  Solved: 7164[Sub ...

  10. sqlserver用timestamp帮助解决数据并发冲突 转【转】

    http://blog.csdn.net/u011014032/article/details/42936783 关于并发请求,网上很多朋友都说的很详细了,我就不在这里献丑了.这里只记录下刚刚完工的那 ...