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 }

 

posted @ 2022-07-25 22:06  江上舟摇  阅读(20)  评论(0编辑  收藏  举报