10.21T6 离散化+二分
Description
N头牛站成一行。每头牛有一个不重复的整数x坐标,以及一个整数标识的品种类型。FJ希望找出长度最小的一段,使得每个品种的奶牛至少有一头。
Input
第一行: 奶牛数N(1 <= N <= 50,000)..
行 2..1+N:两个整数,行 j+1表示第 j奶牛的X坐标及种类(范围在32位int内).
行 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<<'\n'; 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\n", min); 44 return 0; 45 }
over
over