题目:
分析:虽然是之前做过的,虽然是一道经典的题,虽然大标题已经给出了是分治。
但是自己准备开始写暴力时,才想到了分治哦。
是左边不断分治,右边还要排序吗?
不是,看到是分治也没想起来怎么做!
看题解才想到:
左右两边都排好了,然后找左边一个和右边另一个的逆序对,会吗? 会,那就是归并排序基础上进行修改,最后终止条件就是只有一个或者两个元素。
代码:使用lower_bound(),Tle:
#include<bits/stdc++.h>
using namespace std;
int m;
int A[500005];
int B[500005];
int ans=0;
void f(int x,int y)
{
if(x==y) return;
if(x+1==y)
{
if(A[x]>A[y]) {
ans++; swap(A[x],A[y]);
}
return;
}
int c=(x+y)/2;
f(x,c);
f(c+1,y);
for(int i=x;i<=c;i++)
{
int cc=lower_bound(A+c+1,A+y+1,A[i])-A-c-1;
ans=ans+cc;
}
int b1=x,b2=c+1;
int bb=x;
while(1)
{
if(b1==c+1 && b2==y+1) break;
if(b1==c+1)
{
B[bb]=A[b2];bb++;b2++;
}
else if(b2==y+1)
{
B[bb]=A[b1];bb++;b1++;
}
else{
if(A[b1]>A[b2])
{
B[bb]=A[b2];bb++;b2++;
}
else{
B[bb]=A[b1];bb++;b1++;
}
}
}
for(int i=x;i<=y;i++)
{
A[i]=B[i];
}
}
int main()
{
cin>>m;
for(int i=0;i<m;i++) cin>>A[i];
f(0,m-1);
cout<<ans;
}
应该在归并合并的时候进行统计:
#include<bits/stdc++.h>
using namespace std;
int m;
int A[500005];
int B[500005];
int ans=0;
void f(int x,int y)
{
if(x==y) return;
if(x+1==y)
{
if(A[x]>A[y]) {
ans++; swap(A[x],A[y]);
}
return;
}
int c=(x+y)/2;
f(x,c);
f(c+1,y);
int b1=x,b2=c+1;
int bb=x;
while(1)
{
if(b1==c+1 && b2==y+1) break;
if(b1==c+1)
{
B[bb]=A[b2];bb++;b2++;
}
else if(b2==y+1)
{
B[bb]=A[b1];bb++;b1++;
}
else{
if(A[b1]>A[b2])
{
B[bb]=A[b2];bb++;b2++;
ans=ans+c-b1+1;
}
else{
B[bb]=A[b1];bb++;b1++;
}
}
}
for(int i=x;i<=y;i++)
{
A[i]=B[i];
}
}
int main()
{
cin>>m;
for(int i=0;i<m;i++) cin>>A[i];
f(0,m-1);
cout<<ans;
}