第17节 兔子的逆序对(归并排序)

5 篇文章 0 订阅

第17节 兔子的逆序对

一个逆序对(i,j) 需要满足 i < j 且 ai > aj
兔子可以把区间[L,R] 反转,例如序列{1,2,3,4} 反转区间[1,3] 后是{3,2,1,4}。
兔子有m次反转操作,现在兔子想知道每次反转后逆序对个数是奇数还是偶数,兔子喜欢偶数,而讨厌奇数。

示例1
输入
4
1 2 3 4
4
1 2
3 4
1 4
2 3
输出
dislike
like
like
dislike

1 ≤ n ≤ 105
1 ≤ m ≤ 2*106
对于所有数据 l ≤ r且 ai 是n的一个排列,即ai互不相同且ai ≤ n
由于读入数据较大,建议使用快速读入。

#include<bits/stdc++.h>
using namespace std;
const int N=1e7+10;
typedef long long ll;
ll cot=0;
ll a[N],b[N];
void merge(int l,int mid,int r)
{
	int p1=l,p2=mid+1;
	for(int i=l;i<=r;i++)//存下归并后的数组
	{
		if(p2>r||(p1<=mid&&a[p1]<a[p2]))//后半段没有数字了,或者p1指向小数时
		{
			b[i]=a[p1];
			p1++;//指针右移
		} 
		else//逆序或者左边部分读完的情况 
		{
			b[i]=a[p2];
			p2++; //指针右移
			cot+=mid-p1+1;//记录逆序对的个数 ,这些数与p2指向的数形成逆序对(当左边数组读完时,p1=mid+1,cot+0
            //cot&=1;//奇数为1,偶数为0
		}
	}
	for(int i=l;i<=r;i++)
	{
		a[i]=b[i];//将临时数组b[i]中的数转移到原数组a中 
	} 
}

void erfen(int l,int r)
{
	int mid=(l+r)>>1;//除以2 
	if(l<r)
	{
		erfen(l,mid);
		erfen(mid+1,r);
	}
	merge(l,mid,r);
}

int main()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	erfen(1,n); 
    int m;
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        ll l,r;
        scanf("%lld%lld",&l,&r);
        cot+=(r-l+1)*(r-l)/2;//cn2,l--r的范围内取两个数
        cot&=1;
        if(cot) printf("dislike\n");
        else printf("like\n");
    }
	return 0;
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值