洛谷:P1908 逆序对(分治,典型的在分治排序基础上修改)

题目:

分析:虽然是之前做过的,虽然是一道经典的题,虽然大标题已经给出了是分治。

但是自己准备开始写暴力时,才想到了分治哦。

是左边不断分治,右边还要排序吗?

不是,看到是分治也没想起来怎么做!

看题解才想到:

在这里插入图片描述

左右两边都排好了,然后找左边一个和右边另一个的逆序对,会吗? 会,那就是归并排序基础上进行修改,最后终止条件就是只有一个或者两个元素。

代码:使用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)
{
    
    //包括下标为x和下标为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);
 //for(int i=0;i<m;i++) cout<<A[i]<<' ';
 //cout<<endl;
 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)
{
    
    //包括下标为x和下标为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++;
   //ans=ans+y-c+1;
  }
  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);
 //for(int i=0;i<m;i++) cout<<A[i]<<' ';
 //cout<<endl;
 cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/weixin_42721412/article/details/108544938