通师高专科技创新社周赛Round 16

CF1669B Triple

题目链接

题意

给定一个包含 n 元素的数组 a,输出至少出现三次的任何值,如果没有这样的值,则输出 -1。

思路

  1. 利用map统计每个数出现的次数
  2. 将第一个出现次数>=3的数输出
  3. 当没有这样的值输出-1

坑点

代码
#include<bits/stdc++.h>
using namespace std;
const int N  = 2e5  +10;
int a[N];
int main()
{
        int t;
        cin >> t;
        while (t -- )
        {
                int n; 
                cin >> n;
                map<int, int> ma;
                int ans = -1;//初值为-1
                for (int i = 1; i <= n; i ++ )
                {
                        int x;
                        cin >> x;
                        ma[x] ++;
                        if (ma[x] >= 3) 
                        {
                            ans = x;
                        }
                }
                cout << ans << endl;
        }
        return 0;
}

总结

签到题

CF1671B Consecutive Points Segment

题目链接

题意

给出 n 个数 x_1, x_2, …, x_n 保证序列 x 严格递增。对于每个数 x_i,这个数只能选择改变成 x_i - 1或x i +1,当然,也可以不变。问能不能使所有数构成一个连续整数段。可以输出 YES,否则输出 NO。

思路

  1. 序列包装严格递增的,只需判断首尾的数的差值
  2. 找到极限的范围确定首尾差的最大值为n+1
  3. 当在范围内时,可以达到

坑点

代码
#include<bits/stdc++.h>
using namespace std;
const int N  = 2e5  +10;
int a[N];
int main()
{
        int t;
        cin >> t;
        while (t -- )
        {
                int n; 
                cin >> n;
                for (int i = 1; i <= n; i ++ )
                {
                        int x;
                        cin >> a[i];
                }
                if (a[n] - a[1] <= n + 1) cout << "YES" << endl;//找到极限的范围确定首尾差的最大值为n+1
                else cout << "NO" << endl;
        }
        return 0;
}

总结

简单思维题

CF680A Bear and Five Cards

题目链接

题意

给定5个正整数,你可以从中去除2个或3个相同的数。如果没有相同的数,即不能去除。求去除1次后剩余数字的最小和。

思路

  1. 想要输出的和最小和,那减少的就要最大
  2. 找到2个或3个相同的数的和最大的减去

坑点

代码
#include<bits/stdc++.h>
using namespace std;
const int N  = 2e5  +10;
int a[N];
int main()
{
        int sum = 0;//计算初始的和
        for (int i = 1; i <= 5; i ++ )
        {
                cin >> a[i];
                sum += a[i];
        }
        int maxn = 0;
        for (int i = 1; i <= 5; i ++ )//找到相同2个数的最大和
        {
            for (int j = i + 1; j <= 5; j ++ )
            {
                if (a[i] == a[j])
                {
                    maxn = max(a[i] * 2, maxn);
                }
            }
        }
        for (int i = 1; i <= 5; i ++ )//找到3个数的最大和
        {
            for (int j = i + 1; j <= 5; j ++ )
            {
                for (int k = j + 1; k <= 5; k ++ )
                {
                    if (a[i] == a[j] && a[j] == a[k])
                    {
                        maxn = max(a[i] * 3, maxn);
                    }
                }
            }
        }
        cout << sum - maxn << endl;
        return 0;
}

总结

简单模拟题

CF701A Cards

题目链接

题意

现在有n张卡牌(n为偶数),每张卡牌上都写着一个正整数。有n/2个人要玩这个卡牌游戏,在游戏开始时每个人会得到两张卡牌,每张卡牌只能给一个玩家。 现在让你发卡牌,使每一个人手上的卡片上所写的数字的总和相等。数据保证有发牌的方案符合题目要求。

思路

  1. 每个人两张牌要使得总和相等,先按从小到大排序
  2. 利用两个指针分别指向首尾,依次向中间推进
  3. 因为需要输出对应卡片的位置可以利用结构体保存对应数字和位置号

坑点

  1. 数据保证有发牌的方案符合题目要求
代码
#include<bits/stdc++.h>
using namespace std;
struct name{
        int xu;//位置号
        int s;//对应数字
}a[110];
bool cmp(name x,name y)//按从小到大排序
{
        if(x.s==y.s)
        {
                return x.xu<y.xu;
        }
        else{
                return x.s<y.s;
        }
}
int main()
{
        int n;
        cin>>n;
        int b[1110];
        for(int i=1;i<=n;i++)
        {
                cin>>a[i].s;
                a[i].xu=i;//赋值每个位置号
        }
        sort(a+1,a+1+n,cmp);
        int l=1,r=n;//利用两个指针
        while(l<r)
        {
                cout<<a[l].xu<<" "<<a[r].xu<<endl;
                l++;
                r--;
        }
        return 0;
}

总结

结构体,贪心,需要注意细节

CF1623C Balanced Stone Heaps

题目链接

题意

你有 nn 堆石子,其中第 ii 堆里面有 h_i 粒石子。你需要从第 3 堆石子开始从前往后进行操作。设当前为第 i 堆石子,你可以选择一个在 [0,h_i/3]的整数 d,从第 ii堆石子中取出 3d粒石子,然后往第 i-1堆石子里放入 d 粒石子,往第 i-2 堆石子里放入 2d 粒石子。
你需要通过合理设计操作方案,使得数量最少的一堆石子的数量最大。请求出这个最大值。

思路

  1. 利用二分先确定这个最小值
  2. 从后往前遍历当大于最小值时可以将当前的分给前两个位置,最后判断最初1,2位置是否满足

坑点

  1. d的范围在[0,hi/3]之间
代码
#include<bits/stdc++.h>
using namespace std;
const int N  = 2e5  +10;
int a[N], b[N];
int n;
bool check(int x)
{
    for (int i = 1 ; i <= n; i ++ ) b[i] = a[i];//b为每堆石子的变化,a为初始的石子
    for (int i = n; i >= 3; i -- )
    {
        if (b[i] < x) return false;
        
        int d=(b[i]-x)/3;
        d = min(d, a[i]/3);//d的范围在[0,hi/3]之间
        b[i-1] += d;
        b[i-2] += 2*d;
    }
    if(b[1]>=x&&b[2]>=x) return true;//当1,2位置的石子满足条件
    else return false;
}
int main()
{
        int t;
        cin >> t;
        while (t -- )
        {
            cin >> n;
            for (int i = 1; i <= n; i ++ )
            {
                    cin >> a[i];
            }
            int l = 0, r = 0x3f3f3f3f;
            while (l < r)//利用二分寻找最大值
            {
                int mid = l + r + 1 >> 1;
                if (check(mid)) l = mid;
                else r = mid - 1;
            }
            cout << l << endl;
        }
        
        return 0;
}

总结

二分答案题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霖承科技 LinChance

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值