线段树求序列逆序数

题意,给出一段序列,并将序列前的n-1个数字一次放到序列后面,形成新序列,并求出所有序列中的最小逆序数,可用枚举法和线段树解题
事实上,只需求出一段序列的逆序数即可推出另一段的如序列a0a1…an-1是由0到n-1组成的序列,把a0调到后面,则减少的逆序数为a0个,增加 n-1-a0个

 #include <iostream>
  using namespace std;//线段树求逆序数 
  const int k=5500;
  struct  node{ int left,right,num;
  } tree[4*k];
  void build(int left,int right ,int node)
  {
  	tree[node].left=left;
  	tree[node].right=right;
  	tree[node].num=0;
  	if(left==right)
  	   return;
  	   int mid=(left+right)>>1;
  	 
	   
	   	build(left,mid,node<<1);
	   	build(mid+1,right,node<<1|1);
				
  	
   } 
   int  search(int left,int right,int node)
   {
   	if(tree[node].left==left&&tree[node].right==right)
   	    return tree[node].num; 
   	      int mid=(tree[node].left+tree[node].right)>>1;
   	      if(right<=mid) return  search( left,right,node<<1);
   	      else if(left>mid) return search( left,right,node<<1|1  );
   	      else  return search( left,mid,node<<1)+search( mid+1,right,node<<1|1  );
   	    
   	
   	
   }
  void new_ (int x,int b)
   { 
   
   	
   	if(tree[b].left==tree[b].right){ tree[b].num++; return  ;}
   	int mid=(tree[b]. left+tree[b].right)>>1;
   	if( x<=mid )   new_(x,b<<1);
   	else    new_(x,b<<1|1);
   	  
   	tree[b].num=tree[b<<1].num+tree[b<<1|1].num;
   }
int main() {
  int a[k];
  int n,min;
  while(cin>>n)
  {
  	build(0,n-1,1);
  	for(int i=0;i<n;i++)
  	{ cin>>a[i];
	  }
	  int sum=0;
	  for(int i=0;i<n;i++)
	  {  sum+=search(a[i],n-1,1);
	     new_(a[i],1);
	     
	  }
	  min=sum;
  	for(int i=0;i<n-1;i++)
  	     { sum=sum-a[i]+n-a[i]-1;
  	       if(min>sum) min=sum;
		   }
		   cout<<min<<endl;
  }



	return 0;
	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_43983124

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值