10.21T6 离散化+二分

Description

  N头牛站成一行。每头牛有一个不重复的整数x坐标,以及一个整数标识的品种类型。FJ希望找出长度最小的一段,使得每个品种的奶牛至少有一头。

Input

  第一行: 奶牛数N(1 <= N <= 50,000)..
  行 2..1+N:两个整数,行 j+1表示第 j奶牛的X坐标及种类(范围在32位int内).

Output

  1行:最短长度

Sample Input

6 25 7 26 1 15 1 22 3 20 1 30 1

Sample Output

4

Hint

【样例说明】选出第1、2、4号牛
 
 
本人做法:
我用vector记录了一下每个编号的时候的所有位置并排了个序
然后对于每一个点向右二分每一个不同编号并在里面取最大值,在最大值里面找最小值
就完了
 
官方做法:

模拟扫描法用不更新简单枚举法。维护start—>end区间,记录区间内牛的种类数和每种种类的牛的只数。将牛按坐标排序。

先固定start,找到符合要求的end并计算结果,之后增加start,再继续找end.由于start与end都只向后扫,则时间复杂度为O(n)

本人code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<algorithm>
 5 #include<map>
 6 #define N 4000005
 7 using namespace std;
 8 vector<int>number[500001],so;
 9 map<int,int>vis;
10 struct node{
11     int pos,type;
12 }e[N];
13 bool cmp(const node &a,const node&b){
14     return a.pos<b.pos;
15 }
16 int d[50001];
17 int main(){
18     int n;
19     cin>>n;
20     int cnt=0;
21     for(int i=1;i<=n;i++){
22         cin>>e[i].pos>>e[i].type;
23         d[++cnt]=e[i].type;
24     }
25     sort(d+1,d+cnt+1);
26     cnt=unique(d+1,d+cnt+1)-d-1;
27     for(int i=1;i<=n;i++){
28         e[i].type=lower_bound(d+1,d+cnt+1,e[i].type)-d;
29     }
30     sort(e+1,e+n+1,cmp);
31     for(int i=1;i<=n;i++){
32         number[e[i].type].push_back(e[i].pos);
33 //        cout<<e[i].type<<" "<<e[i].pos<<'
';
34         if(vis[e[i].type])continue;
35         so.push_back(e[i].type);
36         vis[e[i].type]=1;
37     }
38     int min0=0x3f3f3f3f;
39     for(int i=1;i<=n;i++){
40         int max0=0;
41         int flag=0;
42         for(int j=0;j<so.size();j++){
43             if(e[i].pos>number[so[j]][number[so[j]].size()-1]){
44                 flag=1;
45                 break;
46             }
47             int pos=lower_bound(number[so[j]].begin(),number[so[j]].end(),e[i].pos)-number[so[j]].begin();
48             max0=max(max0,number[so[j]][pos]-e[i].pos);
49         }
50         if(flag)continue;
51         min0=min(min0,max0);
52     }
53     cout<<min0;
54     return 0;
55 }

官方code:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <map>
 4 #include <set>
 5 #include <iostream>
 6 using namespace std;
 7 struct Cow {
 8     int loc, id;
 9 }  cows[50000];
10 
11 bool cmp(const Cow &a, const Cow &b) {
12     return a.loc<b.loc;
13 }
14 int main() {
15     int num_IDS, N, i, num_in_map = 0, A[50000], IDS[50000], start, end, min;
16     map<int, int> breeds;
17     set<int> ID_set;
18     scanf("%d", &N);
19     for(i=0; i<N; i++) {
20         scanf("%d %d", &cows[i].loc, &cows[i].id);
21         ID_set.insert(cows[i].id);
22         breeds[cows[i].id] = 0;
23     }
24     sort(cows, cows+N, cmp);//按坐标排序
25     num_IDS = ID_set.size();//种类数
26     start = 0;//开始位置
27     end = 0;//结束位置
28     min = 1<<30;//初值
29     while(1) {
30         while(num_in_map!=num_IDS && end<N) { //如果未找到包含全部种类区间
31             if(breeds[cows[end].id]==0) num_in_map++;//映射中如果该类不存在,则加1
32             breeds[cows[end++].id]++;//记值,结束区间加1
33         }
34         if(end==N && num_in_map!=num_IDS)   break;//如果结束了还未找到则退出
35         while(breeds[cows[start].id]>1)//如果开始位置的牛在区间多于一个,则start加1
36             breeds[cows[start++].id]--;
37         //计算stat到end的区间长度并PK原来的
38         if(cows[end-1].loc-cows[start].loc<min) min = cows[end-1].loc-cows[start].loc;
39         //新的开始区间,start++,原start的种类减1,区间内总的种类数减1
40         breeds[cows[start++].id]--;
41         num_in_map--;
42     }
43     printf("%d
", min);
44     return 0;
45 }

over

over

原文地址:https://www.cnblogs.com/saionjisekai/p/9827085.html