題面(from luogu)
P3029 [USACO11NOV]牛的陣容Cow Lineup
題目背景
【問題描述】
農民約翰僱一個專業攝影師給他的部分牛拍照。由於約翰的牛有好多品種,他喜歡他的照片包含每
個品種的至少一頭牛。
約翰的牛都站在一條沿線的不同地方, 每一頭牛由一個整數位置 X_i以及整數品種編號 ID_i表示。
約翰想拍一張照片,這照片由沿線的奶牛的連續範圍組成。照片的成本與規模相當,這就意味着,在一
系列照片中的最大和最小 X 座標的差距決定了照片的成本。
請幫助約翰計算最小的照片成本,這些照片中有每個不同的品種的至少一頭牛,沒有兩頭牛願意站
在同一個地點的。
【輸入格式】
第 1 行:牛的數量 N;
第 2…1+N 行:每行包含 2 個以空格分隔的正整數 X_i 和 ID_i;意義如題目描述;
【輸出格式】
輸出共一行,包含每個不同品種 ID 的照片的最低成本。
【輸入樣例】
6 25 7 26 1 15 1 22 3 20 1 30 1 【輸出樣例】
4 【輸入說明】在不同的座標點 25,26,15,22,20,30 中有六頭牛
【輸出說明】在約翰的牛中,從 X=22 到 X=26(整個規模爲 4)包含了每個的不同品種的 ID 3,7 和 1。
【數據規模】
對於 50%的數據: 1≤N≤300;
對於 100%的數據:1≤N≤50,000;0≤X_i≤1,000,000,000;1≤ID_i≤1,000,000,000;
感謝uid=15936的翻譯
題目描述
Farmer John has hired a professional photographer to take a picture of some of his cows. Since FJ’s cows represent a variety of different breeds, he would like the photo to contain at least one cow from each distinct breed present in his herd.
FJ’s N cows are all standing at various positions along a line, each described by an integer position (i.e., its x coordinate) as well as an integer breed ID. FJ plans to take a photograph of a contiguous range of cows along the line. The cost of this photograph is equal its size – that is, the difference between the maximum and minimum x coordinates of the cows in the range of the photograph.
Please help FJ by computing the minimum cost of a photograph in which there is at least one cow of each distinct breed appearing in FJ’s herd.
依次給出N頭牛的位置及種類,要求找出連續一段,使其中包含所有種類的牛,問:這連續的一段最小長度是多少?
輸入格式
-
Line 1: The number of cows, N (1 <= N <= 50,000).
-
Lines 2…1+N: Each line contains two space-separated positive integers specifying the x coordinate and breed ID of a single cow. Both numbers are at most 1 billion.
輸出格式
- Line 1: The smallest cost of a photograph containing each distinct breed ID.
輸入輸出樣例
輸入 #1 複製
6
25 7
26 1
15 1
22 3
20 1
30 1
輸出 #1 複製
4
說明/提示
There are 6 cows, at positions 25,26,15,22,20,30, with respective breed IDs 7,1,1,3,1,1.
The range from x=22 up through x=26 (of total size 4) contains each of the distinct breed IDs 1, 3, and 7 represented in FJ’s herd.
感謝 wjcwinmt 提供題目簡述
題目分析
我們首先來簡要分析一下題目的意思:求包涵所有種類的奶牛的照片的最小成本
首先,我們先處理奶牛的種類的問題。
因爲對於每一個種類都在10億之間徘徊,所以離散化是必然的
如果不用離散化而是直接寫多重的循環來的話,時間複雜度會給你上一課的
當然在完成了離散化之後,我們就可以巧妙的當成“桶”來做了
之後是對於照片的長度的處理了
根據題意,我們不妨可以得知,所有的奶牛都是相當於在一條數軸上面的
故排序是必然的
之後在我們得到了一串單調遞增的數
到這裏,我們可以想到維護隊列
那麼當前符合條件的照片的成本就是隊列的長度了
當然對於隊列中的每一個元素,我們都是有座標和種類之分的,這裏可以用到結構體 (不說也知道)
之後便是到了隊列的維護環節了
首先我們先考慮其的符合條件——有所有種類的奶牛,在這裏我們可以用一個變量來存儲當前不同奶牛的數目,便是在每一次當前種類的第一次入隊時累加
在入隊方面沒有是好說的,相關的量自己來改變
之後是到了出隊的環節了
剛開始,我的思路遇到了一個新添加的隊尾元素,如果其種類與隊首的元素像重複,那麼,隊首出隊
但是這樣寫的話
得分只有67分
爲什麼呢?
下面給出反例:
5
1 1
2 2
3 2
4 3
5 1
很明顯,我們要得到的答案是 5-3=2
但是用上面的哪一種方法來維護的話,答案就會得到3
這又是爲何呢?
因爲在每一個元素入隊的時候,我們只是將其與隊首相對比,但是在需要求的最優的一種隊列中會出現浪費的情況——一種奶牛出現了多次!
下面給出模擬的過程
第一次:
位置:1
種類:1
第二次:
位置:1 2
種類:1 2
第三次:
位置:1 2 3
種類:1 2 2
第四次:
位置:1 2 3 4
種類:1 2 2 3 現在已經包含了所有種類的奶牛,進行一次求和,答案爲3
第五次:
位置:1 2 3 4 5
種類:1 2 2 3 1 當前的隊尾與隊首的種類相同——出隊,故:
位置:2 3 4 5
種類:2 2 3 1 當前已經包含了所有種類的奶牛,進行一次求和,答案仍然爲3
根據上面的過程,我們能很明顯的看出在進行到第五次時,出現了明顯的浪費——2重複了——目前隊首的元素出現了重複,這樣的話就達不到最優解的要求了,
所以在這裏,我們要對重複的隊首元素不斷地出隊
對每一次新得到的隊首,對其唯一性判斷——我們每一個種類只需要一個,這纔是符合最優解的要求,除非情況特殊
對於重複的隊首元素,因爲在後面已經有所包涵,故,踢出隊列去
這樣的話,在一般的情況下,只有在一個元素剛剛入隊時,且隊首的元素並沒有重複時,我們的種類的個數纔有一定的可能重出現,但是如果已經是最後一個奶牛,那麼,這也是最優的解
代碼
#include <bits/stdc++.h>
using namespace std;
long long b[50009];
long long ans = 9999999999;
int w,t,i,n,s = 1;
int v[50009];
struct node { //結構體,x表示位置,y表示種類
long long x;
long long y;
}a[50009],p[50009];
bool cmp(node k,node z) {
return k.x < z.x;
}
int main() {
scanf("%d",&n);
for (i = 1; i <= n; i++) {
scanf("%lld %lld",&a[i].x,&a[i].y);
b[i] = a[i].y; //b是用於離散化的工具數組
}
sort(a+1,a+n+1,cmp); //給a排序,讓其呈現類似數軸的狀態
//離散化3步走
sort(b+1,b+n+1); //排序
int num = unique(b+1,b+n+1) - b - 1; //去重
for (i = 1; i <= n; i++) a[i].y = lower_bound(b+1,b+num+1,a[i].y) - b; //找到自己新的位置
t = w = i = 1 ; //t表示隊首,w表示隊尾,從第一個元素開始入隊
p[t].x = a[1].x; p[t].y = a[1].y; //入隊
v[p[t].y]++; //當前的種類出現過一次了
for (int i = 2; i <= n; i++) {
w++, p[w].x = a[i].x, v[a[i].y]++, p[w].y = a[i].y; //入隊操作
if (v[p[w].y] == 1) s++; //新種類,當前不同種類數累加
while (v[p[t].y] > 1) { //出隊處理,對多餘的額外部分的處理,每個種類儘量保留一個以求最優
v[p[t].y]--,t++; //當前種類數減少,踢走隊頭
}
if (s == num) { //當前有所有的種類的奶牛了
long long L = p[w].x - p[t].x; ans = min(ans,L); //計算長度,取最小值
}
}
printf("%lld",ans);
return 0; //wan mei jie shu
}
crx CSP-J/S RP++