题目描述 https://www.luogu.org/problemnew/show/P1908
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入输出格式
输入格式:
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。序列中每个数字不超过10^9
输出格式:
给定序列中逆序对的数目。
输入输出样例
输入样例#1: 复制
6
5 4 2 6 3 1
输出样例#1: 复制
11
请使用较快的输入输出
说明 二分法的思路我以前就知道,但是实践的时候还是花了两个小时
1. 两个有序数列合并的时候出现问题
2. 结果超出范围,应该是longlong 类型,体现是前10个通过,后10个没有通过 应知道这种情况首先考虑超出范围。
#include <cstdio>
#include <cmath>
#include <vector>
#include <map>
#include <stack>
#include <sstream>
#include <algorithm>
#include <iostream>
using namespace std;
long long icount=0;
vector<int> vt,vtt;
int main() {
void dp(int l,int h);
int n;
cin>>n;
vt.resize(n);
vtt.resize(n);
for(int i=0; i<n; i++) {
scanf("%d",&vt[i]);
// cin>>vt[i];
}
dp(0,n-1);
cout<<icount<<endl;
}
void dp(int low,int high) {
if(high<=low) return;
int mid=(high+low)/2;
dp(low,mid);
dp(mid+1,high);
for(int i=low; i<=mid; i++)
vtt[i]=vt[i];
int i=low,j=mid+1,k=low;
while(i<=mid) {
if(vtt[i]<=vt[j]||j>high) {
vt[k]=vtt[i];
i++;
} else {
icount+=(mid-i+1);
vt[k]=vt[j];
j++;
}
k++;
}
}