洛谷:P1966 火柴排队(提高+/省选-,分治)

题目:

洛谷:P1966 火柴排队(提高+/省选-,分治)_第1张图片

分析:起初没有思路,看一眼题解是归并排序。所以自己先想了想。

如果一个是有序的,那么另一个也是有序的,这样才会得到最小值。

那么问题转化为一串数字,交换最小次数后使其有序。

想了半天没想到,仔细看题解,

发现漏掉了相邻才可以移动。(意识到这道题在leetcode 上应该也做过,当时也是没看清相邻的要移动)

很明确了,左右两边的移动成为有序的会多余吗?

感性认识不会。

强调:只需要考虑向前移动的或者是只需要考虑向后移动的,是这样的!!!!!(标记为精华原因所在)

值得细想!

因此,只考虑前移的,那么一定只有后半部分里面里面有前移动的。而且是在两个指针都没有指向最后一个元素的时候,即两部分都有元素待放入。

代码:??状态不好,暂且放下。

洛谷:P1966 火柴排队(提高+/省选-,分治)_第2张图片

#include
using namespace std;
#include
using namespace std;
int m;
int B[100005];
int ans=0;
struct node{
     
 int x1;
 int x2;
} A[100005];
bool cmp(node n1,node n2)
{
     
 return n1.x2<n2.x2;
}
void f(int x,int y)
{
     //包括下标为x和下标为y的。   从小到大排序 
 if(x==y) return;
 if(x+1==y)
 {
     
  if(A[x].x1>A[y].x1) {
     
   ans++; swap(A[x].x1,A[y].x1);
   ans=ans%(100000000-3);
  }
  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].x1;bb++;b2++;
  }
  else if(b2==y+1)
  {
     
   B[bb]=A[b1].x1;bb++;b1++;
  }
  else{
     
   if(A[b1].x1>A[b2].x1) 
   {
     
    B[bb]=A[b2].x1;bb++;b2++;
    ans=ans+b2-bb;
    ans=ans%(100000000-3);
    }
   else{
     
    B[bb]=A[b1].x1;bb++;b1++;
   }
  }
 }
  for(int i=x;i<=y;i++)
  {
     
    A[i].x1=B[i];
 }
}
int main()
{
     
  cin>>m; 
  for(int i=0;i<m;i++) cin>>A[i].x1;
  for(int i=0;i<m;i++) cin>>A[i].x2;
  sort(A,A+m,cmp);
  /*for(int i=0;i
  f(0,m-1);
  cout<<ans;
}

你可能感兴趣的:(分治,我认为的精华,杂篇)