https://www.luogu.org/problem/P1908
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
Update:数据已加强。
输入格式
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。序列中每个数字不超过1e9
输出格式
给定序列中逆序对的数目。
输入输出样例
输入 #1 复制
6
5 4 2 6 3 1
输出 #1 复制
11
说明/提示
输入包含多个测试用例,每个测试用例第一行为一个整数n(n<500000)表示数组的长度,下面n行每一行包含一个整数0≤a[i]≤999,999,999,即数组中第i个元素的值。当n=0时结束输入
请使用较快的输入输出
应该不会n方过50万吧 by chen_zhe
//离散化
洛谷“学无止境”大佬题解关键
#include <iostream>
#include<algorithm>
#include <stdio.h>
#include <string>
#include <string.h>
#include <map>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <deque>
using namespace std;
typedef long long ll;
const int N=500010;
ll n,ans=0;
struct sa
{
ll x,y;
}p[N];
int cmp(sa a,sa b)
{
if(a.x==b.x)
return a.y<b.y;
else
return a.x<b.x;
}
ll a[N],b[N];
ll lowbit(ll n)
{
return n&(-n);
}
ll update(ll x,ll y)
{
for(;x<=n;x+=lowbit(x))
a[x]+=y;
}
ll sum(ll x)
{
ll ans=0;
for(;x;x-=lowbit(x))
ans+=a[x];
return ans;
}
int main()
{
scanf("%lld",&n);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&p[i].x);
p[i].y=i;
}
sort(p+1,p+n+1,cmp);
for(ll i=1;i<=n;i++)
b[p[i].y]=i;
for(ll i=1;i<=n;i++)
{
update(b[i],1);
ans=ans+(i-sum(b[i]));
}
printf("%lld\n",ans);
return 0;
}
.///,…,…,.//另一种形式的离散化,可以自动解决数据有重复的问题
#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <map>
#include <math.h>
#include <vector>
#include <set>
#include <queue>
#include <map>
#include <deque>
using namespace std;
typedef long long ll;
const int N=5e5+7;
ll n;
ll tree[N],a[N],b[N];
void update(ll x,ll y)
{
for(;x<=n;x+=(x&-x))
tree[x]+=y;
}
ll sum(ll x)
{
ll ans=0;
for(;x;x-=(x&-x))
ans+=tree[x];
return ans;
}
int main()
{
while(scanf("%d",&n)!=-1&&n) {
memset(tree,0, sizeof(tree));
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
ll m = unique(b + 1, b + n + 1) - b - 1;
for (int i = 1; i <= n; i++)
a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
ll ans = 0;
for (int i = 1; i <= n; i++) {
update(a[i], 1);
ans += (i - sum(a[i]));
}
printf("%lld\n", ans);
}
return 0;
}
掌握了归并排序之后,再加入新题解