zoukankan      html  css  js  c++  java
  • CF986B Petr and Permutations(逆序对)

    题目描述

    Petr likes to come up with problems about randomly generated data. This time problem is about random permutation. He decided to generate a random permutation this way: he takes identity permutation of numbers from 11 to nn and then 3n3n times takes a random pair of different elements and swaps them. Alex envies Petr and tries to imitate him in all kind of things. Alex has also come up with a problem about random permutation. He generates a random permutation just like Petr but swaps elements 7n+17n+1 times instead of 3n3n times. Because it is more random, OK?!

    You somehow get a test from one of these problems and now you want to know from which one.

    输入格式

    In the first line of input there is one integer nn ( 103≤n≤106103≤n≤106 ).

    In the second line there are nn distinct integers between 11 and nn — the permutation of size nn from the test.

    It is guaranteed that all tests except for sample are generated this way: First we choose nn — the size of the permutation. Then we randomly choose a method to generate a permutation — the one of Petr or the one of Alex. Then we generate a permutation using chosen method.

    输出格式

    If the test is generated via Petr's method print "Petr" (without quotes). If the test is generated via Alex's method print "Um_nik" (without quotes).

    题意翻译

    Petr要打乱排列。他首先有一个从 11 到 nn 的顺序排列,然后进行 3n3n 次操作,每次选两个数并交换它们。

    Alex也要打乱排列。他与Petr唯一的不同是他进行 7n+17n+1 次操作。

    给定一个 11 到 nn 的排列。问是由谁打乱的。如果是Petr,输出"Petr",否则输出"Um_nik"(不是Alex)

    感谢@AKEE 提供翻译

    输入输出样例

    输入 #1复制

    5
    2 4 5 1 3
    

    输出 #1复制

    Petr
    

    有引理:交换一个排列的两个数,序列的逆序对的奇偶性必然发生变化。

    证明可以大致yy一下:当交换的两个数x,y距离小于等于1的时候易证,当大于1的时候将两个数之间的这些数分为三部分(设较大的数为y):大于y的,小于x的以及大于x且小于y的,分别分析逆序数的变化情况即可(注意夹起来的这部分元素自己的逆序数是不变的)。因为一开始整个排列是有序的,逆序数为0,所以若最终的逆序数为奇数说明交换了奇数次,否则交换了偶数次。因此判断一下3n的奇偶性和逆序数相同还是7n+1的奇偶性和逆序数相同即可。洛谷题解区有On做法更牛逼Orz

    #include <bits/stdc++.h>
    #define N 1000005
    using namespace std;
    int n, a[1000005], b[1000005];
    void add(int x, int y) {
    	for(; x <= N; x += (x & -x)) b[x] += y;
    }
    int ask(int x) {
    	int ans = 0;
    	for(; x; x -= x & -x) {
    		ans += b[x];
    	}
    	return ans;
    }
    int main() {
    	cin >> n;
    	int cnt = 0;
    	for(int i = 1; i <= n; i++) {
    		cin >> a[i];
    		cnt += ask(n) - ask(a[i]);//因为是排列 不会有相同的数
    		add(a[i], 1);
    	}
    	//逆序对数一开始是0,交换3n次后应该为偶数,交换7n+1次后应该为奇数
    	if((cnt & 1) == ((3 * n) & 1)) puts("Petr");
    	else puts("Um_nik");
    	return 0;
    }
    
  • 相关阅读:
    一个自动化测试工具 UI Recorder
    通俗理解http2.0
    IE 问题集合
    webpack
    性能工具集合
    网络 问题
    css命名规范
    ajax 总结
    CSS深入理解学习笔记之relative
    jQuery插件开发通用框架
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/15087637.html
Copyright © 2011-2022 走看看