第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;
}