题解 CF986B 【Petr and Permutations】
首先,我们需要一个引理:交换序列的任意两元素,序列的逆序数的奇偶性必定发生改变。
如何证明?
反正我不会证我是手推瞎猜的
显然
那么
算出给定序列逆序数,判断奇偶性即可。
这里
树状数组
我们记
记
那么逆序数个数就是
开一个桶,从
我们来模拟这个过程,以上文提到的序列为例。
最后累加,得出逆序数。
可这跟树状数组有什么关系?
每次求和就是区间求和,
至于树状数组是什么...qwq
参考代码:
#include <cstdio>
const int MAXN = 1000005;
int tree[MAXN], n, a[MAXN], ans = 0;
int lowbit(int x)
{
return x & -x;
} //lowbit qwq
void insert(int pos, int k)
{
if (pos < 1) return;
while (pos <= n)
{
tree[pos] += k;
pos += lowbit(pos);
}
} //单点修改
int query(int pos)
{
int ret = 0;
while (pos)
{
ret += tree[pos];
pos -= lowbit(pos);
}
return ret;
} //(1-pos)的查询,查询[l,r]的和用query(r)-query(l-1)
int main()
{
scanf("%d", &n);
int i;
for (i = 1; i <= n; i++) scanf("%d", &a[i]);
for (i = 1; i <= n; i++)
{
ans = (ans + query(n) - query(a[i] - 1)) % 2;
//直接记录答案的奇偶性了,query(n)-query(a[i]-1)是sum(a[i],n)
insert(a[i], 1);
//单点修改
}
ans %= 2;
if ((ans - 3 * n) % 2 == 0) printf("Petr"); //奇偶性判断
else printf("Um_nik");
return 0;
}