Luogu P5948 【[POI2003]Chocolate】

Description

传送门


Solution

每次选择花费最大的地方切,然后按照题意(O(n))模拟即可。

证明如下:

(1.)若两次切割都是横向或竖向,且花费小的比花费大的先切割。
设花费小的切割的时候需要切割(a)次,花费大的切割的时候需要切割(b)次,因为中间可能切割了任意次另外一个方向,所以(a 。
那么将它们交换,则花费大的对答案的贡献一定小于等于原先的贡献,所以同一方向将花费大的放在花费小的前面一定最优。
(2.)若两次切割不是同一方向,且话费晓得比花费大的先切割。
设切割前若切花费小的方向花费小的方向需要切(a)刀,切花费大的方向需要切(b)刀。
那么先切花费小的,花费大的就需要切(b + 1)刀,反之亦然。
因为花费大的(\times (b + 1) +)花费小的(\times a >=)花费大的(\times b +)花费小的(\times (a + 1)),所以先切花费大的一定最优。
所以最后复杂度就是排序的复杂度。

[Q.E.D. ]


Code

#include 
#include 
#include 
#include 
using namespace std;
#define ll long long
const int N = 20000;
int n, m, num, sum[2];
struct Node
{
    int cost, type;
} cut[N + 50];
void Read(int &x)
{
    x = 0; int p = 0; char st = getchar();
    while (st  '9') p = (st == '-'), st = getchar();
    while (st >= '0' && st <= '9') x = (x << 1) + (x << 3) + st - '0', st = getchar();
    x = p ? -x : x;
    return;
}
bool Cmp(Node a, Node b)
{
    return a.cost > b.cost;
}
int main()
{
    ll ans = 0;
    Read(n); Read(m);
    for (int i = 1, x; i <= n - 1; i++) Read(x), cut[++num] = (Node){x, 1};
    for (int i = 1, x; i <= m - 1; i++) Read(x), cut[++num] = (Node){x, 0};
    sort(cut + 1, cut + num + 1, Cmp);
    for (int i = 1; i <= num; i++)
    {
        ans = ans + 1LL * (sum[cut[i].type ^ 1] + 1) * cut[i].cost;
        sum[cut[i].type]++;
    }
    printf("%lld", ans);
    return 0;
}
全部评论

相关推荐

HR_丸山彩同学:你的项目描述里,系统设计讲了很多:MemCube是什么、三级存储架构怎么设计、四种遗忘策略分别是什么。这些面试的时候讲没问题,但简历上不需要这么细。 简历要突出的是影响力,不是实现细节。面试官看简历的时候想知道的是「这个项目有多大价值」,不是「这个项目具体怎么实现的」。实现细节是面试时候聊的 怎么改:技术细节可以精简为一句「采用三级存储架构+四种遗忘策略」,把省出来的篇幅用来写影响力。比如:项目有没有开源?有没有写成技术博客?有没有被别人使用过? 校园经历没有任何信息量,任何人都可以写这句话,写了等于没写。更关键的是,你投的是技术岗,校园活动经历本来就不是加分项。如果非要写,必须写出具体的数字和成果。如果你没有这些数字,那就老老实实删掉 「端到端耗时缩减30-40%」要给出确切数字和绝对值。从1000ms降到600ms是降了40%,从100ms降到60ms也是降了40%,但这两个含义完全不一样。其他也是,涉及到数据,准备好证据,口径统一,面试会问 「熟练」「熟悉」「了解」混在一起用,读起来很乱。而且「了解前端需求」最好改成「具备前后端协作经验」
点赞 评论 收藏
分享
02-10 13:41
西南大学 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务