2025牛客寒假算法基础集训营6部分题解

1 前言:

最后一场,做了五题就早早下班了

2 题解

A https://ac.nowcoder.com/acm/contest/95338/A

签到题,不多说

int n;
    cin >> n;
    arr[n + 1] = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> arr[i];
    }
    int cnt = 0;
    for (int i = 1; i <= n; i++)
    {
        if (arr[i] != arr[i + 1])
        {
            cnt++;
        }
    }
    cout << cnt << endl;

K 鸡翻题

很容易注意到页数之和一次翻页变化为4,求出当前页数之和sumsumy再与mod4即可

void solve()
{
    int a, b;
    cin >> a >> b;
    if(abs(2*a+1-b)%4==0)
    {
        cout << "YES" << endl;
    }
    else
    {
        cout << "NO" << endl;
    }
}

L https://ac.nowcoder.com/acm/contest/95338/L

贪心题
先存下除了"CHICKEN"以外的字母的数量,为了尽量全部消除,消除时应该优先消除数量最大的字母。但是不能直接把数量最多的字母全部消除,这是因为在这个过程中会别的字母可能成为数量最大的字母。这时我们可以发现,只要最大的字母的数量不超过剩下字母的数量和,过程中自动让最大的与剩下的消除,一定能消除到只剩一个(字母总和为奇数)或完全消除。

string s = "CHICKEN";
map<char, int> mp;
void init()
{
}
void solve()
{
    int n, tot = 0, N = 7;
    mp = map<char, int>();
    string str;
    cin >> n;
    cin >> str;
    str = '0' + str;
    for (int i = 1; i <= n; i++)
    {
        if (tot < N && s[tot] == str[i])
        {
            tot++;
            continue;
        }
        mp[str[i]]++;
    }
    int maxn = 0, sum = 0;
    for (auto it : mp)
    {
        maxn = max(maxn, it.second);
        sum += it.second;
    }

    if (maxn > sum - maxn || sum % 2 == 1 || tot != 7)
    {
        cout << "NO" << endl;
    }
    else
    {
        cout << "YES" << endl;
    }
}

C 数列之和

这题是队友做的,瞪眼后打表,找到规律就过了,期间被卡溢出,要开unsigned long long。

void solve()
{
    int k;
    cin >> k;
    vector<int> index2n;
    unsigned long long nownum = 2;
    for (int i = 1; i <= 60; i++)
    {

        nownum = nownum * 2;
        if (2e18 < nownum)
        {
            break;
        }
        index2n.push_back(nownum / 2);
    }
    int ckss = k;
//////
    int iterss = 0;
    while (index2n[iterss] <= ckss)
    {
        
        iterss++;
        ckss++;
        if (iterss >= index2n.size())
        {
            break;
        }
    }

    cout << ckss * 2 << endl;
}

I 小鸡的排列构造的checker

离线+树状数组
简化一下题目,我们要知道ci对应的数(以下记为arr[ci])为区间[l,r]中第几小的。将询问按arr[ci]排序后,<=arr[ci]的数是不断增加的,初始化一个全为0的数组,用树状数组单点修改ci位置为1,再求区间[l,r]中1的数量就是我们要求的结果,再按询问的原序输出答案

struct que
{
    int l;
    int r;
    int c;
    int cindex;
    int id;
    int ans = 0;
};
map<int, int> mp;
int arrtree[100005] = {0};
int arr[100005];
que question[300005];

int ans[300005];
int n, m, tot = 0;

bool cmp(que &a, que &b)
{
    return a.c < b.c;
}
bool cmp1(que &a, que &b)
{
    return a.id < b.id;
}
int lowbit(int x)
{
    return x & (-x);
}
int query(int le, int ri)
{
    int sum = 0;
    for (int i = ri; i >= 1; i -= lowbit(i))
        sum += arrtree[i];
    for (int i = le - 1; i >= 1; i -= lowbit(i))
        sum -= arrtree[i];
    return sum;
}
void update(int index, int x)
{
    for (int i = index; i <= n; i += lowbit(i))
        arrtree[i] += x;
}
void init()
{
    tot = 1;
    memset(arrtree, 0, sizeof(arrtree));
}
void solve()
{
    init();
    cin >> n >> m;

    for (int i = 1; i <= n; i++)
    {
        int tmp;
        cin >> tmp;
        arr[i] = tmp;
        mp[tmp] = i;
    }
    for (int i = 1; i <= m; i++)
    {
        int l, r, c;
        cin >> l >> r >> c;
        question[i].l = l, question[i].r = r, question[i].c = arr[c], question[i].cindex = c;
        question[i].id = i;
    }
    sort(question + 1, question + 1 + m, cmp);

    for (int i = 1; i <= m; i++)
    {
        int l = question[i].l, r = question[i].r;
        while (tot < question[i].c)
        {
            update(mp[tot], 1);
            tot++;
        }
        question[i].ans = query(l, r);
    }
    sort(question + 1, question + 1 + m, cmp1);
    for (int i = 1; i <= m; i++)
    {
        cout << question[i].ans + question[i].l << endl;
    }
}

J 铁杵磨成针

不难发现,磨刀的天数一定是前面连续的若干天。在攻击的方案不变的前提下,如果隔了几个回合再磨刀,将磨刀提前不会导致总伤害变小。因为可以在同一个回合磨刀和攻击,磨刀石一定是尽量全用,所以只要前min(n,y)个回合都磨刀,再遍历开始攻击的回合就可以得出答案。

int n, x, y;
void solve()
{
    cin >> n >> x >> y;
    int ans = 0;
    for (int i = 1; i <= min(y, n) + 1; i++)
    {
        int sum = 0, nowat = x;
        nowat += (i - 1);

        if (y <= n)
        {
            sum += (nowat + 1) * (y - (i - 1));
        }
        else
        {
            sum += (nowat + 1) * (n - (i - 1));
        }

        int less = max((int)0, n - y);

        int tmp = max((int)0, nowat - less);
        sum += nowat * (nowat + 1) / 2 - tmp * (tmp + 1) / 2;
        ans = max(ans, sum);
    }
    cout << ans << endl;
}

3 总结

posted @   青一凡  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示