交换次数的奇偶性和逆序对总数的奇偶性是一致的 当结论记住
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define ll long long struct node { int l; int r; ll val; }; node tree[4000010]; ll pre[1000010]; int num[1000010]; int n; void pushup(int cur) { tree[cur].val=tree[cur*2].val+tree[cur*2+1].val; return; } ll query(int pl,int pr,int cur) { ll res; if(pl<=tree[cur].l&&tree[cur].r<=pr) { return tree[cur].val; } res=0; if(pl<=tree[cur*2].r) res+=query(pl,pr,cur*2); if(pr>=tree[cur*2+1].l) res+=query(pl,pr,cur*2+1); return res; } void update(int tar,int cur) { if(tree[cur].l==tree[cur].r) { tree[cur].val=1; return; } if(tar<=tree[cur*2].r) update(tar,cur*2); else update(tar,cur*2+1); pushup(cur); return; } void build(int l,int r,int cur) { int m; tree[cur].l=l; tree[cur].r=r; tree[cur].val=0; if(l==r) return; m=(l+r)/2; build(l,m,cur*2); build(m+1,r,cur*2+1); pushup(cur); return; } int main() { ll ans; int i; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&num[i]); } build(1,n,1); for(i=1;i<=n;i++) { if(num[i]<n) { pre[i]+=query(num[i]+1,n,1); } update(num[i],1); } build(1,n,1); for(i=n;i>=1;i--) { if(num[i]>1) { pre[i]+=query(1,num[i]-1,1); } update(num[i],1); } ans=0; for(i=1;i<=n;i++) { ans+=pre[i]; } ans/=2; if(ans%2==(3*n)%2) printf("Petr\n"); else printf("Um_nik\n"); return 0; }