P1338 末日的傳說 逆序數對

2022-07-23 08:15:17 字數 1539 閱讀 4871

只要是參加jsoi活動的同學一定都聽說過hanoi塔的傳說:三根柱子上的金片每天被移動一次,當所有的金片都被移完之後,世界末日也就隨之降臨了。

在古老東方的幻想鄉,人們都採用一種奇特的方式記錄日期:他們用一些特殊的符號來表示從1開始的連續整數,1表示最小而n表示最大。創世紀的第一天,日曆就被賦予了生命,它自動地開始計數,就像排列不斷地增加。

我們用1-n來表示日曆的元素,第一天日曆就是  1, 2, 3, … n

第二天,日曆自動變為 1, 2, 3, … n, n-1……每次它都生成乙個以前未出現過的「最小」的排列——把它轉為n+1進製後數的數值最小。

日子一天一天地過著。有一天,一位預言者出現了——他預言道,當這個日曆到達某個上帝安排的時刻,這個世界就會崩潰……他還預言到,假如某乙個日期的逆序達到乙個值m的時候,世界末日就要降臨。

什麼是逆序?日曆中的兩個不同符號,假如排在前面的那個比排在後面的那個更大,就是乙個逆序,乙個日期的逆序總數達到m後,末日就要降臨,人們都期待乙個賢者,能夠預見那一天,到底將在什麼時候到來?

輸入格式:

只包含一行兩個正整數,分別為n和m。

輸出格式:

輸出一行,為世界末日的日期,每個數字之間用乙個空格隔開。

輸入樣例#1: 複製

5 4

輸出樣例#1: 複製

1 3 5 4 2

對於10%的資料有n <= 10。

對於40%的資料有n <= 1000。

對於100%的資料有 n <= 50000。

所有資料均有解。

思路:我們知道,逆序對的個數,在最大情況下,是n*(n-1)/2。

所以列舉位置1—n,計算i放在當前位置時,後面能產生的最多逆序對是多少,如果能超過m,就把i放在當前位置。

如果不能,說明這個數太小了,需要放在後面增加逆序對個數,把它扔到未確定區間的最後乙個。

同時,因為把乙個小數放到了後面,接下來未確定區間中不管有多少逆序對,其中的每乙個數,都會與這個數產生一對逆序對,所以我們需要減小m,減小的長度就是區間長度。

**:

1 #include"

bits/stdc++.h"2

#define ll long long

3#define cl(x) scanf("%lld",&x)

4#define pl(x) printf("%lld\n",x)

5using

namespace

std;

6const

int n = 1e6 + 5;7

ll n,m;

8int

a[n];

9int

main()

17for(int i=1;i<=n;i++) printf("

%d%c

",a[i],i==n?'

\n':'');

1819

return0;

20 }

P1338 末日的傳說 (逆序對)

題目鏈結 題面 題解 如何讓逆序對數為m的序列字典序最小呢?假設位置p是最後乙個原始序列的位置,那這個點應該盡量靠右,才能使得字典序最小。而為了保證有m個逆序對,要求p後面的逆序對數盡量大。需要降序排列。這樣問題就轉成找點p,同時在找到p時還需要知道 m 後面所有逆序對數剩餘的值,這個值要在點p身上...

P1338 末日的傳說

首先審題,題目中提到 每次它都生成乙個以前未出現過的 最小 的排列。其實這句話的意思就是說,我這個日期每天都會變化,每次變化後的排列都是以前沒出現過的,也就是不會有重複的排列,然後這個日期還是除了以前出現過的排列之外的最小的排列,也就是說啊,我這個日期是按照一定規律來變化的,第一天是字典序最小,第二...

洛谷P1338(末日的傳說)

只要是參加jsoi活動的同學一定都聽說過hanoi塔的傳說 三根柱子上的金片每天被移動一次,當所有的金片都被移完之後,世界末日也就隨之降臨了。在古老東方的幻想鄉,人們都採用一種奇特的方式記錄日期 他們用一些特殊的符號來表示從1開始的連續整數,1表示最小而n表示最大。創世紀的第一天,日曆就被賦予了生命...