Codeforces Global Round 2 E. Pavel and Triangles

本文探讨了一道算法题,即如何使用不同长度的棍子(长度为2的幂次方)组成尽可能多的三角形。通过分析输入的棍子数量,采用贪心算法策略,实现了最大数量的三角形构建,同时确保每个棍子最多被用于一个三角形。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

E. Pavel and Triangles
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Pavel has several sticks with lengths equal to powers of two.

He has a0 sticks of length 20=1, a1 sticks of length 21=2, …, an−1 sticks of length 2n−1.

Pavel wants to make the maximum possible number of triangles using these sticks. The triangles should have strictly positive area, each stick can be used in at most one triangle.

It is forbidden to break sticks, and each triangle should consist of exactly three sticks.

Find the maximum possible number of triangles.

Input
The first line contains a single integer n (1≤n≤300000) — the number of different lengths of sticks.

The second line contains n integers a0, a1, …, an−1 (1≤ai≤109), where ai is the number of sticks with the length equal to 2i.

Output
Print a single integer — the maximum possible number of non-degenerate triangles that Pavel can make.

Examples
inputCopy
5
1 2 2 2 2
outputCopy
3
inputCopy
3
1 1 1
outputCopy
0
inputCopy
3
3 3 3
outputCopy
3
Note
In the first example, Pavel can, for example, make this set of triangles (the lengths of the sides of the triangles are listed): (20,24,24), (21,23,23), (21,22,22).

In the second example, Pavel cannot make a single triangle.

In the third example, Pavel can, for example, create this set of triangles (the lengths of the sides of the triangles are listed): (20,20,20), (21,21,21), (22,22,22).

题目是说给你n个数,你可以进行两种操作,一种是把一个数减去3,另一种是把对任意的i<j,把ai减去1,把aj减去2。但所有的数都不能减到小于0。
用两个变量,ans记录答案,cnt记录我们选了多少个当前减2,前面任选一个减1。我们考虑从后往前贪心,如果当前值为1,那么如果cnt有值,那么我们就–cnt,++ans。否则,如果当前值ai是偶数,那么我们拿走ai/2个2,也就是cnt+=ai/2,ans+=ai/2,如果当前值ai是奇数,那么我们先拿走一个3,也就是++ans,ai-=3,然后ai就变成了偶数,就按照之前描述的操作。贪心完了以后我们发现我们还需要拿走cnt个1,但我们现在已经把所有的ai清零了,所以我们得从ans里面扣除一部分将cnt补成负数,因为一次操作会使整个数组的所有数之和减3,也就是说–ans可以让cnt-=3,我们将需要减去的cnt减去即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
typedef long long ll;
ll ans,cnt;
int z[maxn];
int n;
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i)
        scanf("%d", z + i);
    for (int i = n; i >= 1; --i)
    {
        if (z[i] % 2 == 0)
        {
            ans += z[i] / 2;
            cnt += z[i] / 2;
        }
        else if (z[i] == 1)
        {
            if (cnt)
                --cnt;
        }
        else
        {
            ++ans;
            z[i] -= 3;
            ans += z[i] / 2;
            cnt += z[i] / 2;
        }
    }
    if (cnt)
        ans -= (cnt + 2) / 3;
    printf("%lld\n", ans);
    return 0;
}

 

### 关于Codeforces Round 704 Div. 2 的信息 对于Codeforces Round 704 Div. 2的比赛,虽然未直接提及具体题目解析或参赛体验的内容,但是可以根据平台的一贯风格推测该轮比赛同样包含了多种算法挑战。通常这类赛事会涉及数据结构、动态规划、图论等方面的知识。 考虑到提供的参考资料并未覆盖到此特定编号的比赛详情[^1],建议访问Codeforces官方网站查询官方题解或是浏览社区论坛获取其他选手分享的经验总结。一般而言,在赛后不久就会有详细的解答发布出来供学习交流之用。 为了帮助理解同类型的竞赛内容,这里提供了一个基于过往相似赛事的例子——如何通过居中子数组特性来解决问题的方法: ```cpp // 假设有一个函数用于处理给定条件下的数组恢复问题 vector<int> restoreArray(vector<vector<int>>& adjacentPairs) { unordered_map<int, vector<int>> adj; for (auto& p : adjacentPairs){ adj[p[0]].push_back(p[1]); adj[p[1]].push_back(p[0]); } int start = 0; for(auto& [num, neighbors] : adj){ if(neighbors.size() == 1){ start = num; break; } } vector<int> res(adjacentPairs.size() + 1); unordered_set<int> seen; function<void(int,int)> dfs = [&](int node, int idx){ seen.insert(node); res[idx] = node; for(auto next : adj[node]){ if(!seen.count(next)){ dfs(next, idx + 1); } } }; dfs(start, 0); return res; } ``` 上述代码展示了利用深度优先搜索(DFS)重建原始序列的一种方式,这与某些情况下解决Codeforces比赛中遇到的问题思路相吻合[^4]。 #### 注意事项 由于缺乏针对Codeforces Round 704 Div. 2的具体材料支持,以上解释更多依赖于对同类活动的理解以及编程技巧的应用实例来进行说明。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值