acwing 103电影,104货仓选址
103解题报告
题目难度:中
题目大意(样例分析):
选择能让科学家们听懂数最多的电影,如果满足条件的不唯一则在此基础上求能看懂的最多的电影
算法引入:离散化
在一些问题中,我们只关心 n 个数字之间的相对大小关系,而不关心它本身是多少。
离散化是应用在排序算法上的一种思想,基本内容是将一个无限大的集合中所要求的n个有限元素归并到一个集合中,这样可以降低算法的复杂度;同时对于去重后的每个元素a[i]用去重后的m个数(1~m)中在保持有序的条件下进行替换
具体操作是对于原数组a进行去重后排序得到b数组,用b数组的下标i与b[i]建立映射关系,则要查询i替换的数就可以返回b[i],要查询a[j]被哪个数替代,则只需返回排名即在b数组中查找a[j]的位置
void discrete()//离散化 { sort(lan+1,lan+1+cnt1); for(int i=1;i<=cnt1;i++) { if(i==1||lan[i]!=lan[i-1]) { dis[++cnt2]=lan[i]; } } } int query(int x)//查找 { return lower_bound(dis+1,dis+1+cnt2,x)-dis; }
解题思路:题目中所有电影和人所涉及的语言最多是2*m+n中,对所有电影和语言进行离散化处理,并且统计每个科学家所懂的语言的数量,最后统计结果;
参考代码:
1 #include<bits/stdc++.h>//acwing 进阶103 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 const int N=2e5+10; 6 int a[N]; 7 int b[N]; 8 int c[N]; 9 int n,m; 10 int ans; 11 int lan[N*4]; 12 int sum[N*4]; 13 int dis[N*4]; 14 int cnt1,cnt2; 15 void discrete()//离散化 16 { 17 sort(lan+1,lan+1+cnt1); 18 for(int i=1;i<=cnt1;i++) 19 { 20 if(i==1||lan[i]!=lan[i-1]) 21 { 22 dis[++cnt2]=lan[i]; 23 } 24 } 25 } 26 int query(int x)//二分 27 { 28 return lower_bound(dis+1,dis+1+cnt2,x)-dis; 29 } 30 signed main() 31 { 32 IOS; 33 cin>>n; 34 for(int i=1;i<=n;i++) 35 { 36 cin>>a[i]; 37 lan[++cnt1]=a[i]; 38 } 39 cin>>m; 40 for(int i=1;i<=m;i++) 41 { 42 cin>>b[i]; 43 lan[++cnt1]=b[i]; 44 } 45 for(int j=1;j<=m;j++) 46 { 47 cin>>c[j]; 48 lan[++cnt1]=c[j]; 49 } 50 discrete(); 51 for(int i=1;i<=n;i++) 52 { 53 ++sum[query(a[i])];//统计每种语言的人的数量 54 } 55 int ans1=INT_MIN; 56 int ans2=INT_MIN; 57 for(int i=1;i<=m;i++) 58 { 59 int x=query(b[i]); 60 int y=query(c[i]); 61 if(sum[x]>ans1)//优先考虑让很高兴的人最多 62 { 63 ans1=sum[x]; 64 ans2=sum[y]; 65 ans=i; 66 } 67 else 68 { 69 if(sum[x]==ans1&&sum[y]>ans2)//如果答案不唯一、则在此前提下再让比较高兴的人最多 70 { 71 ans1=sum[x]; 72 ans2=sum[y]; 73 ans=i; 74 } 75 } 76 } 77 cout<<ans<<endl; 78 return 0; 79 }
104货舱选址:
难度评价:中
题目大意:一道有趣的数学结论题,题目给定一些商店到一个货仓的距离,要求怎么建货舱使的距离总和最小;
结论:当n是奇数的时候建在最中间a[(n+1)/2]处,当n是偶数的时候建在a[n/2]~a[n/2+1]任意一处即可;
证明:
基本原理|x-a|+|x-b|>=|a-b|;
|a1-x|+|a2-x|+....|an-x|=(|a1-x|+|an-x|)+(|a2-x|+|an-1-x|)+....(|an/2-x|+|an/2+1-x|>=|an-a1|+|an-1-a2|+....
当且仅当取中位数的时候等号成立
解题思路:
进行排序之后取中位数位置进行距离统计,当然也可以不用排序用nth_element求中位数也可以
参考代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define int long long 4 #define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0); 5 const int N=1e5+10; 6 int a[N]; 7 int n; 8 int ans; 9 signed main() 10 { 11 IOS; 12 cin>>n; 13 for(int i=1;i<=n;i++) 14 cin>>a[i]; 15 sort(a+1,a+1+n); 16 int mid; 17 if(n%2==0) 18 { 19 mid=a[n/2]; 20 } 21 else 22 mid=a[(n+1)/2]; 23 for(int i=1;i<=n;i++) 24 { 25 ans+=abs(a[i]-mid); 26 } 27 cout<<ans<<endl; 28 return 0; 29 }
本文来自博客园,作者:江上舟摇,转载请注明原文链接:https://www.cnblogs.com/LQS-blog/p/16519051.html