题意:
给定n,代表原排列为(1,2,3….n)
再给一个排列,问该排列是通过随机3n次交换(两个元素交换位置)还是7n+1次交换得到的。
思路:
1.全排列知识,排列发生一次元素交换,排列的奇偶性改变。
2.求给出排列的逆序数,可以得到该排列 奇偶性,逆序数为奇数即为奇排列,否则为偶排列。
3.因为3n、7n+1本身的奇偶性就不同,因此判断逆序数与3n、7n+1的奇偶性就可以得到答案。
逆序数为奇数,说明给出的排列是由奇数次交换得到的
否则为偶数次交换得到的
求逆序数可以用归并排序或树状数组。。。
代码:(归并排序)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int const maxn=1000005;
int a[maxn];
int b[maxn];
int n;
ll Reverse=0;
int parites(int x){
if(x&1)return 1;
else return 0;
}
void Merge(int l,int r,int ll,int rr){
int i=l;
int j=ll;
int id=l;
while(i<=r&j<=rr){
if(a[i]<=a[j]){
b[id]=a[i];
id++;i++;
continue;
}
else{
Reverse+=(r-i+1);
b[id]=a[j];
j++,id++;
continue;
}
}
while(i<=r){
b[id]=a[i];
i++;
id++;
}
while(j<=rr){
b[id]=a[j];
j++;
id++;
}
for(int i=l;i<=rr;i++){
a[i]=b[i];
}
}
void merge_sort(int l,int r){
if(l<r){
int mid=(l+r)>>1;
merge_sort(l,mid);
merge_sort(mid+1,r);
Merge(l,mid,mid+1,r);
}
else return ;
}
void By_Merge_sort(){
merge_sort(1,n);
//cout<<Reverse<<endl;
if(parites(Reverse)==parites(3*n))
cout<<"Petr";
else
cout<<"Um_nik";
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
By_Merge_sort();
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int const maxn=1000005;
typedef long long ll;
int c[maxn*4];
int a[maxn];
int b[maxn];
int n;
ll Reverse=0;
int parites(int x){
if(x&1)return 1;
else return 0;
}
int lowbit(int x){
return (x&(-x));
}
void Add(int x,int v){
for(int i=x;i<=n;i+=lowbit(i)){
c[i]+=v;
}
}
ll Sum(int x){
ll ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=c[i];
}
return ans;
}
ll ask(int l,int r){
return Sum(r)-Sum(l-1);
}
void By_Binary_Tree(){
ll ans=0;
for(int i=1;i<=n;i++){
Add(a[i],1);
int sm=Sum(a[i]);
ans+=(i-sm);
//cout<<ans<<endl;
}
if(parites(3*n)==parites(ans)){
cout<<"Petr";
}
else
cout<<"Um_nik";
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
By_Binary_Tree();
return 0;
}