LUOGU P3029 [USACO11NOV]牛的陣容Cow Lineup

題面(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++

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章