牛客周赛Round 60(CD)

昨晚的一场牛客周赛,上了100分,但还是只能做不到四题,AB就不说了,觉得C这题挺好的,单独写一下题解吧~

目录

C题

题面描述

思路分析

代码实现

*max(min)_element用法 

D题

题面描述

思路分析

代码实现

C题

题面描述

思路分析

其实思路很好想,主要是借这一题我们要学会一些常见的代码实现,我们可以从题目中看到有m组坐标且不重复,那我们先开一个pair读入每一组数据,当xi = xj 或者 yi = yj 时可以连线,要求距离的最大值,那我们其实可以很自然的联想到map,但是这次要开的map不是存入两个int了,而是存入每一组横坐标或者纵坐标相同时,对应的纵坐标和横坐标,所以应该map应该开一个<int,vector(int)>,用数组来存当一个坐标值相等时,所有每一组的另一个坐标值,然后我们找到数组的最大值和最小值,相减比较找出最大的值即可,即为最终的答案,下面我们看一下代码怎么写——

另外需要注意的是我们在求数组里的最大值和最小值时,第一种方法我们可以直接sort排序一下

直接最右边元素和最左边元素相减就行了,或者我们也可以用*min_element和*max_element得出数组的最大元素和最小元素 

代码实现

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include <iomanip>
#include <cmath>
#include <string>
#include <vector>
#define int long long
#define x first 
#define y second 
using namespace std;
const int N = 1e5 + 10;
//int a[N];
typedef pair<int,int> PII;
PII p[N];
unordered_map<int,vector<int>> row_mp;
unordered_map<int,vector<int>> col_mp;
void solve()
{
     int n,m;
     cin >> n >> m;
     for(int i = 1; i <= m; i++)  cin >> p[i].x >> p[i].y;

     for(auto &c : p)
     {
        int a = c.x;
        int b = c.y;
        row_mp[a].push_back(b);
        col_mp[b].push_back(a);
     }
     int len = 0;
     for(auto &c : row_mp)
     {
        //  const vector<int>& positions = row.second;
         if(c.y.size() > 1)
         {
           /*   int min_pos = *min_element(c.y.begin() , c.y.end());
             int max_pos = *max_element(c.y.begin() , c.y.end()); */
             sort(c.y.begin() , c.y.end());
             len = max(len , c.y[c.y.size() - 1] - c.y[0]);
         }
     }
     for(auto &c : col_mp)
     {
         if(c.y.size() > 1)
         {
            /*  int min_pos = *min_element(c.y.begin() , c.y.end());
             int max_pos = *max_element(c.y.begin() , c.y.end());
             len = max(len , max_pos - min_pos); */
               sort(c.y.begin() , c.y.end());
             len = max(len , c.y[c.y.size() - 1] - c.y[0]);
         }
     }
     cout << len << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr),cout.tie(nullptr);
    int t = 1;
    /*  int t;
     cin >> t; */
    while(t -- ) solve();
    return 0;
}

*max(min)_element用法 

这里我补充一下*max(min)_element用法 ,一样方便后续复习食用,max_element( ) 的函数返回值是个指针,对应的是最大值所对应的位置,*max_element则对应最大值的具体数值,比设置临时变量for循环遍历求解最大(小)值要高效。直接贴个代码就看明白了——

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
int main(int argc, const char * argv[]) {
    int a[] = {-5,-3,-3,-2,7,1}, b[] ={-10,-5,3,4,6};
    cout << *max_element(a, a + 6) << endl;
   // cout << *max_element(a, a + sizeof(a)/sizeof(int)) << endl;
    cout << *min_element(b, b + 5) << endl;
    vector<int> c{-5,-3,-3,-2,7,1}, d{-10,-5,3,4,6};
    cout << *max_element(c.begin(), c.end()) << endl;
    cout << *min_element(d.begin(), d.end()) << endl;
    return 0;
}

输出: 


D题

题面描述

思路分析

本题也是一个思维题,维护一个集合[1 ~ X],表示这个集合能凑出1 - X中任意一个数,首先让星星数组从小到大排序,赛时这题只过了3/5,还是没处理到位,比赛后来看题解是dp的一种想法,如果sum表示的是小于等于sum的数都可以表示出来,那枚举到ai​的时候,sum到sum + ai − 1都可以表示出来。

代码实现

#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;

void solve() {
    int n;
    cin >> n;
    std::vector<int> a(n + 1);
    for(int i=1;i<=n;i++){
        std::cin>>a[i];
    }
    std::sort(a.begin() + 1, a.end());
    int sum = 0;
    for (int i = 1; i <= n; i++) {
        if(sum >= a[i] - 1) {
            sum += a[i];
        }
    }
     if(sum >= n) cout << "Cool!" << endl;
     else cout << sum + 1 << endl; 
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t; 
    while (t--) solve();
    
    return 0;
}

身边的同学考研的考研,考公的考公,而我还在热爱算法竞赛的道路上独自流浪,下一场线上赛就是这周六(9月21日)了,暂时打算这星期就不碰了,周五学校ACM算法协会还要招新,身为会长这学期也是很忙的,慢慢来吧,这星期去刷刷考研数学和准备一下软考了~~~

       我的生活确实充斥着沉闷和平凡,我想,是时候做一些事情了,于是我就去做了——

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值