LUOGU P3029 [USACO11NOV]牛的阵容Cow Lineup

4 篇文章 0 订阅
3 篇文章 0 订阅

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值