洛谷 P3034 Cow Photography G/S——題解

Nightmares_oi發表於2024-09-07

洛谷P3034題解


傳送錨點


摸魚環節

[USACO11DEC] Cow Photography G/S

題面翻譯

題目描述

今天的奶牛們特別調皮!Farmer John 想做的只是給排成一排的奶牛拍照,但是在他拍下照片之前,奶牛們一直在移動。

具體地說,FJ 有 \(N\) 頭奶牛(\(1 \leq N \leq 20\,000\)),每頭奶牛都有一個唯一確定的編號。FJ 想要以一個特定的順序拍下一張奶牛排成一排的照片,這個順序用陣列 \(A[1 \ldots N]\) 表示,其中 \(A[i]\) 代表排在 \(i\) 位置的奶牛的編號。

他按照這樣的順序將奶牛們排列好,但在他按下快門之前,有些奶牛(可能是零頭或任意多頭奶牛,位置也不一定連續)將移到一個新的位置。更準確地說,一些奶牛離開佇列,剩下的奶牛靠攏,這些離開的奶牛再將自己重新插入到佇列中的任意位置(不一定是他們之前的位置)。FJ 感到非常沮喪,他再次按照 \(A\) 陣列的順序重新安排了佇列。但在他再次按下快門之前,又有一些奶牛移動到了新的位置。

就這樣,FJ 拍了五張照片。給出每張照片拍攝的內容(即 FJ 按下快門時奶牛的順序),請你嘗試推算出 FJ 最初為奶牛們排的順序(即 \(A\) 陣列)。由於可能有奶牛移動,照片顯示的順序與原來的順序可能有所不同。但是,一頭奶牛最多隻會移動一次:即如果一頭奶牛在拍其中一張照片時移動了,它在拍其他四張照片的時候都不會移動。當然,由於其他奶牛也在移動,它在不同照片中的順序並不一定相同。

輸入格式

第一行包含一個整數 \(N\)

接下來 \(5N\) 行,每 \(N\) 行描述了一張照片中各奶牛的順序。每行包含一個奶牛的編號,保證所有編號都是不超過 \(1\,000\,000\,000\) 的非負整數。

輸出格式

輸出 \(N\) 行,每行一個整數 \(A[i]\),即 FJ 最初為奶牛排好的順序。

樣例解釋

FJ 拍的五張照片分別為:

  • 10 20 30 40 50
  • 20 10 30 40 50
  • 30 10 20 40 50
  • 40 10 20 30 50
  • 50 10 20 30 40

題目描述

The cows are in a particularly mischievous mood today! All Farmer John wants to do is take a photograph of the cows standing in a line, but they keep moving right before he has a chance to snap the picture.

Specifically, each of FJ's N (1 <= N <= 20,000) cows has a unique integer ID number. FJ wants to take a picture of the cows standing in a line in a very specific ordering, represented by the contents of an array A[1...N], where A[j] gives the ID number of the jth cow in the ordering. He arranges the cows in this order, but just before he can press the button on his camera to snap the picture, a group of zero or more cows (not necessarily a contiguous group) moves to a set of new positions in the lineup. More precisely, a group of zero or more cows steps away from the line, with the remaining cows shifting over to close the resulting gaps in the lineup. The cows who stepped away then re-insert themselves at different positions in the lineup (not necessarily at the locations they originally occupied). Frustrated but not deterred, FJ again arranges his cows according to the ordering in A, but again, right before he can snap a picture, a different group of zero or more cows moves to a set of new positions in the lineup.

The process above repeats for a total of five photographs before FJ gives up. Given the contents of each photograph, see if you can reconstruct the original intended ordering A. Each photograph shows an ordering of the cows that differs from A in that some group of zero or more cows has moved. However, a cow only moves in at most one photograph: if a cow is part of the group that moves in one photograph, she will not actively move in any of the other four photographs (although she could end up at a different index as a consequence of other cows around her moving, of course).

Farmer John居然拍了五張照片,每張表示初始化牛位置的移動後的狀態。然後求出FJ這五頭牛初始化的樣子。

輸入格式

* Line 1: The number of cows, N (1 <= N <= 20,000).

* Lines 2..5N+1: The next 5N lines describe five orderings, each one a block of N contiguous lines. Each line contains the ID of a cow, an integer in the range 0...1,000,000,000.

輸出格式

* Lines 1..N: The intended ordering A, one ID per line.

樣例 #1

樣例輸入 #1

5 
10 
20 
30 
40 
50 
20 
10 
30 
40 
50 
30 
10 
20 
40 
50 
40 
10 
20 
30 
50 
50 
10 
20 
30 
40

樣例輸出 #1

10 
20 
30 
40 
50

提示

There are 5 cows, with IDs 10, 20, 30, 40, and 50. In each of the 5 photos, a different cow moves to the front of the line (at most one cow moves in each photo here, but it is possible in other inputs that multiple cows could move in a particular photo).

The correct original ordering A[1..5] is 10, 20, 30, 40, 50.


又是經典的題面,john與cow的愛情故事john與cow的oi故事,也不知道為啥要給奶牛拍照,咱也不敢問,問了john發力給黑題就完了。於是為了祭拜膜拜john這位oi鼻祖,咱就來寫個藍題。


正片開始

1.草率程式碼

仔細分析樣例可以知道,對於5張照片,只要有奶牛\(A\)在奶牛\(B\)之前出現三次,則奶牛\(A\)一定在奶牛\(B\)之前。由於\(奶牛編號\leq 1000000000\),所以需要用map搞一下。很簡單就能得到以下程式碼。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e6+1;
int n,a[N];
map<int,ll>m[10];//照片編號,奶牛編號——>位置編號
int cmp(int x,int y)
{
    int ans=0;//統計次數
    for(int i=1;i<=5;i++)//遍歷每張照片中x,y的大小關係。
        if(m[i][x]<m[i][y]) ans++;
    return ans>=3;
}
int main()
{
    cin>>n;
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;cin>>x;
            a[j]=x;//每張照片中的元素不變,直接覆蓋即可
            m[i][x]=j;//用map對映關係
        }
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++) cout<<a[i]<<endl;
    return 0;
}

2.懵逼部分

  1. 淺淺分析下複雜度,排序自帶\(5 \cdot nlogn\),基於map內用紅黑樹實現,每次查詢\(logn\),總複雜就是\(5\cdot nlogn \cdot2\cdot logn=10 \cdot n\cdot (logn)^{2}\),將小\(n=20000\)帶入淺算一下,誒嘛直接炸了(但不知道為啥我居然沒祭,難不成是資料太水了是我RP值太高了?)。最佳化演算法,很明顯用雜湊,這裡可以用unordered_map,內部基於雜湊實現,體驗\(o(1)\)查詢的快感。
  2. 實測了一下,最後一個大資料,用原始版map跑了\(334ms\),用上unordered_map的話只需要\(94ms\),大大提升了程式碼的B格容錯率。

完整程式碼

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e6+1;
int n,a[N];
unordered_map<int,ll>m[10];//照片編號,奶牛編號——>位置編號
int cmp(int x,int y)
{
    int ans=0;
    for(int i=1;i<=5;i++)
        if(m[i][x]<m[i][y]) ans++;
    return ans>=3;
}
int main()
{
    cin>>n;
    for(int i=1;i<=5;i++)
    {
        for(int j=1;j<=n;j++)
        {
            int x;cin>>x;
            a[j]=x;
            m[i][x]=j;
        }
    }
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++) cout<<a[i]<<endl;
    return 0;
}

完結收工!!!!!

個人主頁

看完點贊,養成習慣

\(\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\Downarrow\)

相關文章