分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

[Jsoi2011]柠檬

发布时间:2023-09-06 02:17责任编辑:郭大石关键词:暂无标签

Description

Flute 很喜欢柠檬。它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬。贝壳一共有 N (1 ≤ N
≤ 100,000) 只,按顺序串在树枝上。为了方便,我们从左到右给贝壳编号 1..N。每只贝壳的大小不一定相同,
贝壳 i 的大小为 si(1 ≤ si ≤10,000)。变柠檬的魔法要求,Flute 每次从树枝一端取下一小段连续的贝壳,并
选择一种贝壳的大小 s0。如果 这一小段贝壳中 大小为 s0 的贝壳有 t 只,那么魔法可以把这一小段贝壳变成 s
0t^2 只柠檬。Flute 可以取任意多次贝壳,直到树枝上的贝壳被全部取完。各个小段中,Flute 选择的贝壳大小 s
0 可以不同。而最终 Flute 得到的柠檬数,就是所有小段柠檬数的总和。Flute 想知道,它最多能用这一串贝壳
变出多少柠檬。请你帮忙解决这个问题。

Solution

一个奇怪的利用单调栈来优化的dp

Code

#include <vector>#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>const int N = 100005;int cnt[N], S[N], A[N];long long f[N];int n;long long Calc(int Begin, int Len) { ???return f[Begin - 1] + (long long) A[Begin] * Len * Len;}int P(int j1, int j2) { ???int l = 1, r = n, mid, res = n + 1; ???while (l <= r) { ???????mid = l + r >> 1; ???????if (Calc(j1, mid - S[j1] + 1) >= Calc(j2, mid - S[j2] + 1)) ????????????r = mid - 1, res = mid; ???????else l = mid + 1; ???} ???return res;}std:: vector<int> Q[N];#define ET(i) (i->size() > 1)#define F(i, j) (*i)[i->size() - j]int main () { ???scanf("%d", &n); ???for (int i = 1; i <= n; i += 1) { ???????scanf("%d", &A[i]), S[i] = ++cnt[A[i]]; ???????std:: vector<int>* Que = &(Q[A[i]]); ???????while (ET(Que) and P(F(Que, 2), i) <= P(F(Que, 1), i)) ???????????Que->pop_back(); ???????Que->push_back(i); ???????while (ET(Que) and P(F(Que, 2), F(Que, 1)) <= S[i]) ???????????Que->pop_back(); ???????f[i] = Calc(F(Que, 1), S[i] - S[F(Que, 1)] + 1); ???} ???printf("%lld\n", f[n]); ???return 0;}

[Jsoi2011]柠檬

原文地址:https://www.cnblogs.com/qdscwyy/p/9768722.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved