逆序数
题目描述
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如一个序列为4 5 1 3 2, 那么这个序列的逆序数为7,逆序对分别为(4, 1), (4, 3), (4, 2), (5, 1), (5, 3), (5, 2),(3, 2)。
输入描述:
第一行有一个整数n(1 <= n <= 100000), 然后第二行跟着n个整数,对于第i个数a[i],(0 <= a[i] <= 100000)。输出描述:
输出这个序列中的逆序数
思路:用归并排序求逆序对
ac代码:
#include<iostream>
#include<vector>
using namespace std;
#define ll long long
ll cnt=0;
const int N=1e6+10;
int a[N];
void merge(int l,int r,int mid){
int l1=l,r1=mid+1;
int k=0;
vector<int> s(r-l+1);
while(l1<=mid&&r1<=r){
if(a[l1]<=a[r1])
{
s[k++]=a[l1++];
}
else{
s[k++]=a[r1++];
cnt+=mid-l1+1;
}
}
while(l1<=mid){
s[k++]=a[l1++];
}
while(r1<=r){
s[k++]=a[r1++];
}
for(int i=l;i<=r;i++){
a[i]=s[i-l];
}
}
void merge_sort(int l,int r ){
if(l>=r)
return;
int mid =(l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
merge(l,r,mid);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
merge_sort(0,n-1);
cout<<cnt<<endl;
return 0;
}
兔子的逆序对
题目描述
兔子最近喜欢上了逆序对。
一个逆序对(i,j) 需要满足 i < j 且 ai > aj
兔子觉得只是求一个序列的逆序对个数太没有意思了。
于是兔子想到了一个更有趣的问题!
兔子可以把区间[L,R] 反转,例如序列{1,2,3,4} 反转区间[1,3] 后是{3,2,1,4}。
兔子有m次反转操作,现在兔子想知道每次反转后逆序对个数是奇数还是偶数,兔子喜欢偶数,而讨厌奇数。
请注意,每一次反转操作都会对原序列进行改变。例如序列{1,2,3,4} 第一次操作区间[1,2] 后变成{2,1,3,4} 第二次反转区间[3,4] 后变成 {2,1,4,3}输入描述:
第一行一个整数 n,表示序列的大小。 第二行 n 个整数ai 表示序列的各个元素。 第三行一个整数m,表示操作个数。 接下来 m 行,每行两个整数 l,r,表示反转的区间。输出描述:
输出共m行每行一个字符串,表示反转后序列逆序对个数的奇偶性,如果是逆序对个数奇数,输出"dislike"(不含引号),如果是偶数,输出"like"。
思路:先通过归并排序求出刚开始的逆序对数,因为交换一次序列中的两个数,其他数不变,则交换后的序列逆序对奇偶性交换。 反转区间[l,r],相当与前后指针依次交换,交换次数为长度 r-l 除以2.再判断交换次数的奇偶即可解决此问题。
代码:
#include<iostream>
using namespace std;
const int N=1e5+10;
int a[N];
int ans=0;
int w[N];
//归并排序求逆序对
void merge_sort(int l,int r){
if(l>=r) return ;
int mid=(l+r)/2;
merge_sort(l,mid);
merge_sort(mid+1,r);
int i=l,j=mid+1,cnt = l;
while(i<=mid&&j<=r){
if(a[i]<=a[j])
w[cnt++]=a[i++];
else{
ans+=(mid-i+1);
w[cnt++]=a[j++];
}
}
while(i<=mid){
w[cnt++]=a[i++];
}
while(j<=r){
w[cnt++]=a[j++];
}
for(int i=l;i<=r;i++){
a[i]=w[i];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
merge_sort(1, n);
int l,r;
cin>>m;
while(m--){
cin>>l>>r;
int len=r-l+1;
ans=(ans+len/2)%2;
if(ans&1)
cout<<"dislike\n";
else
cout<<"like\n";
}
return 0;
}
(新手上路,有错误希望大家指出。)