C/C++每日一练3

1.简写单词

题目规则

输入一串空格分隔的英文单词,取每个单词首字母转大写拼接输出 示例: 输入:College English Test → 输出:CET 输入:I am Bob → 输出:IAB

C++ 完整代码

cpp

运行

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    while (cin >> s) {
        char c = s[0];
        // 小写转大写
        if (c >= 'a' && c <= 'z') c -= 32;
        cout << c;
    }
    return 0;
}

2.dd爱框框

一、题意

给定长度为 n 的正整数数组,找长度最小的区间 [l, r],满足区间和 ≥ x; 多个同长度最小区间时,输出左端点更小的一组; 数组下标输出为从 1 开始

输入

  1. 第一行:n x(\(1\le n\le 10^7,\ 1\le x\le 10000\))
  2. 第二行:n 个正整数 \(a_i \in [1,1000]\)

示例

输入:

plaintext

10 20
1 1 6 10 9 3 3 5 3 7

区间 3~5:6+10+9=25 ≥20,长度 3,是最短区间 输出:3 5

二、解题思路:滑动窗口(双指针 O (n))

所有数字都是正数,窗口和单调递增,适合滑动窗口:

  1. 右指针不断向右扩大窗口,累加和;
  2. 一旦窗口和 ≥ x,不断收缩左边界,同时更新最优区间;
  3. 记录最小长度,长度相等则保留更早出现的区间。
窗口初始

收缩左边界
缩小窗口
#include <iostream>
#include <vector>
#include <climits>
using namespace std;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr); // 加速输入,处理千万级数据

    int n, x;
    cin >> n >> x;
    vector<int> a(n);
    for (int i = 0; i < n; ++i)
        cin >> a[i];

    long long sum = 0;
    int l = 0, minLen = INT_MAX;
    int ansL = 0, ansR = 0;

    for (int r = 0; r < n; ++r)
    {
        sum += a[r];
        // 当前窗口满足条件,尽量左缩
        while (sum >= x)
        {
            int curLen = r - l + 1;
            // 更短,更新答案;等长不更新(保留左边更小的)
            if (curLen < minLen)
            {
                minLen = curLen;
                ansL = l;
                ansR = r;
            }
            sum -= a[l++];
        }
    }
    // 题目下标从1开始
    cout << ansL + 1 << " " << ansR + 1 << endl;
    return 0;
}

3.除2!

题目分析

题意: 给定长度为 n 的数组,最多进行 k 次操作:每次只能选偶数,把它除以 2。 操作次数不超过 k,求数组总和最小是多少。

核心思路

每次操作收益最大,总和下降最多:

  1. 每次一定选当前最大的偶数除以 2,这样总和减少最多;
  2. 使用大根堆(优先队列)维护数组;
  3. 循环最多 k 次:
    • 取出堆顶最大数;
    • 如果是奇数:没法再除 2,直接退出循环(剩下操作全部浪费);
    • 偶数:除以 2,放回堆,消耗一次操作;
  4. k 次用完或无偶数可操作时,累加堆内所有数即为答案。

C++ 完整代码

cpp

运行

#include <iostream>
#include <queue>
#include <vector>
using namespace std;

int main()
{
    int n, k;
    cin >> n >> k;
    priority_queue<int> heap; // 大根堆

    for (int i = 0; i < n; ++i)
    {
        int x;
        cin >> x;
        heap.push(x);
    }

    while (k--)
    {
        int cur = heap.top();
        heap.pop();
        if (cur % 2 != 0)
        {
            // 奇数无法操作,放回,剩余操作无效
            heap.push(cur);
            break;
        }
        cur /= 2;
        heap.push(cur);
    }

    long long sum = 0;
    while (!heap.empty())
    {
        sum += heap.top();
        heap.pop();
    }
    cout << sum << endl;
    return 0;
}

举例演示

样例 1: 输入:

plaintext

3 3
8 4 2

过程: k=3

  1. 取 8→4,堆:4,4,2,k=2
  2. 取 4→2,堆:4,2,2,k=1
  3. 取 4→2,堆:2,2,2,k=0 总和:6

样例 2:

plaintext

2 5
5 16

操作: 16→8 (k4)→4 (k3)→2 (k2)→1 (k1),此时 1 是奇数,剩余 1 次操作作废 数组:5,1,总和 6

细节说明

  1. 要用 long long 求和,防止大数溢出;
  2. 遇到奇数直接终止循环,后续操作没有意义;
  3. 贪心正确性:每次削减最大偶数,总和下降幅度最优。
谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

c23856

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

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

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

打赏作者

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

抵扣说明:

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

余额充值