LuoguP5504 [JSOI2011]柠檬
LuoguP5504 [JSOI2011]柠檬
题目描述
Solution
容易发现一个性质:每一段划分区间的首尾两个元素相同。
因为倘若不相同的话其中至少一个元素也就不产生贡献,将其划分在其他区间一定不会变劣。
因此就可以写出一个简单的O(n2)O(n^2)O(n2)的dpdpdp。
fi=fj−1+(si−sj+1)2(ai=aj)f_i=f_{j-1}+(s_i-s_j+1)^2\;\;\;\;\;\;\;(a_i=a_j) fi=fj−1+(si−sj+1)2(ai=aj)
其中sis_isi表示在iii之前的与iii相同的元素的个数。
考虑决策单调性:
设有j1<j2<ij_1<j_2<ij1<j2<i,aj1=aj2a_{j_1}=a_{j_2}aj1=aj2,令getans(x,y)getans(x,y)getans(x,y)表示fx−1+(sy−sx+1)2f_{x-1}+(s_y-s_x+1)^2fx−1+(sy−sx+1)2。
若getans(j1,i)≥getans(j2,i)getans(j_1,i)\geq getans(j_2,i)getans(j1,i)≥getans(j2,i),则对于所有i′≥ii'\geq ii′≥i,都有getans(j1,i′)≥getans(j2,i′)getans(j_1,i')\geq getans(j_2,i')getans(j1,i′)≥getans(j2,i′),因为两者的增长都是平方级别的。
因此我们可以用单调栈维护这一过程。
对于每一种aia_iai开一个单调栈,我们希望的是保证栈中元素的getans(...,i)getans(...,i)getans(...,i)始终递增。每次如果发现栈顶元素没有它下面一个元素优,就弹栈。
但这并不是完全正确的,随着iii的后移,因为前面的元素增长快,所以可能存在一个j1<j2<j3<ij_1<j_2<j_3<ij1<j2<j3<i,使得getans(j1,i)>getans(j3,i)getans(j_1,i)>getans(j_3,i)getans(j1,i)>getans(j3,i),但getans(j2,i)<getans(j3,i)getans(j_2,i)<getans(j_3,i)getans(j2,i)<getans(j3,i)。
因此我们还需要保证栈中每一个元素xxx超过上面一个元素yyy的时间小于yyy超过它上面的元素zzz的时间。
这个某个元素超过另一个元素的时间可以二分求得。
所以我们维护单调栈时额外添加一个判断getans(stack[top−2])>getans(stack[top−1])getans(stack[top-2])>getans(stack[top-1])getans(stack[top−2])>getans(stack[top−1])的时间是否比getans(stack[top−1])>getans(stack[top])getans(stack[top-1])>getans(stack[top])getans(stack[top−1])>getans(stack[top])的时间短即可。
时间复杂度O(nlgn)O(nlgn)O(nlgn)。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <cassert>
#include <string.h>
//#include <unordered_set>
//#include <unordered_map>
//#include <bits/stdc++.h>#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se secondusing namespace std;template<typename T>inline bool upmin(T &x,T y) { return y<x?x=y,1:0; }
template<typename T>inline bool upmax(T &x,T y) { return x<y?x=y,1:0; }typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int,int> PR;
typedef vector<int> VI;const lod eps=1e-11;
const lod pi=acos(-1);
const int oo=1<<30;
const ll loo=1ll<<62;
const int mods=998244353;
const int MAXN=600005;
const int INF=0x3f3f3f3f;//1061109567
/*--------------------------------------------------------------------*/
inline int read()
{int f=1,x=0; char c=getchar();while (c<'0'||c>'9') { if (c=='-') f=-1; c=getchar(); }while (c>='0'&&c<='9') { x=(x<<3)+(x<<1)+(c^48); c=getchar(); }return x*f;
}
ll f[MAXN];
vector<int> V[MAXN];
int a[MAXN],s[MAXN],cnt[MAXN],n;
ll Getans(int x,int y) { return f[x-1]+1ll*a[x]*y*y; }
ll getans(int x,int y) { return f[x-1]+1ll*a[x]*(s[y]-s[x]+1)*(s[y]-s[x]+1); }
int check(int x,int y)
{int l=s[y],r=n+1;while (l<r){int mid=(l+r)>>1;if (Getans(x,mid-s[x]+1)>=Getans(y,mid-s[y]+1)) r=mid;else l=mid+1;}return r;
}
int main()
{n=read();for (int i=1;i<=n;i++) s[i]=++cnt[a[i]=read()];f[0]=0;for (int i=1,sz;i<=n;i++){sz=V[a[i]].size()-1;while (sz>=1&&check(V[a[i]][sz-1],V[a[i]][sz])<=check(V[a[i]][sz],i)) V[a[i]].pop_back(),sz--;V[a[i]].PB(i),sz++;while (sz>=1&&getans(V[a[i]][sz-1],i)>=getans(V[a[i]][sz],i)) V[a[i]].pop_back(),sz--;f[i]=getans(V[a[i]][sz],i);}printf("%lld\n",f[n]);return 0;
}
LuoguP5504 [JSOI2011]柠檬相关推荐
- bzoj 4709: [Jsoi2011]柠檬(分段DP+决策单调性)
4709: [Jsoi2011]柠檬 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 240 Solved: 105 [Submit][Status ...
- bzoj4709 [Jsoi2011]柠檬
Description Flute很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有\(N(1\le N\le 100000)\)只,按顺序串在树枝上.为了方便,我们 ...
- 【bzoj4709】[Jsoi2011]柠檬 斜率优化
题目描述 给你一个长度为 $n$ 的序列,将其分成若干段,每段选择一个数,获得 $这个数\times 它在这段出现次数的平方$ 的价值.求最大总价值. $n\le 10^5$ . 输入 第 1 行:一 ...
- 单调队列优化和决策单调性优化
前言:dp蒟蒻拼命挽救一下dp a....,会围绕三个"形如"来写...但更重要的是本质理解啊qwq A.单调队列优化: 有时状态转移方程形如f[i][j]=min{f[i-1][ ...
- [暑假的bzoj刷水记录]
(这篇我就不信有网站来扣) 这个暑假打算刷刷题啥的 但是写博客好累啊 堆一起算了 隔一段更新一下. 7月27号之前刷的的就不写了 , 写的累 代码不贴了,可以找我要啊.. 2017.8.27upd ...
- 斜率优化dp 的简单入门
不想写什么详细的讲解了...而且也觉得自己很难写过某大佬(大米饼),于是建议把他的 blog 先看一遍,然后自己加了几道题目以及解析...顺便建议看看算法竞赛(蓝皮书)的 0x5A 斜率优化(P294 ...
- LeetCode简单题之柠檬水找零
题目 在柠檬水摊上,每一杯柠檬水的售价为 5 美元.顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 美元或 20 美元.你必 ...
- 图解:数据结构中的6种「树」,柠檬问你心中有数吗?
数据结构这门课程是计算机相关专业的基础课,数据结构指的是数据在计算机中的存储.组织方式. 我们在学习数据结构时候,会遇到各种各样的基础数据结构,比如堆栈.队列.数组.链表.树...这些基本的数据结构类 ...
- LeetCode 860.柠檬水找零(C++)
在柠檬水摊上,每一杯柠檬水的售价为 5 美元. 顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯. 每位顾客只买一杯柠檬水,然后向你付 5 美元.10 美元或 20 美元.你必须给 ...
最新文章
- 学习动力之“学习金字塔 (爱德加•戴尔)”理论
- python Elasticsearch 排序
- [vue-cli]vue-cli怎么解决跨域的问题?
- python数独代码_python 实现计算数独
- C/C++小游戏 ——贪吃蛇
- idea迁移到其他电脑,省去重新安装破解及配置
- Windows Server 2012 MSDN原版 简体中文 版下载
- java udp 接收16进制_java UDP通信中十六进制的接收与发送
- UCGUI动态内存分析
- Materials studio中的简单聚合物的建立及盒子的弛豫
- log4j 日志书写格式_Log4J日志配置详解
- 如何使用win10自带的录屏工具录制视频
- android字体文件制作教程,Android使用自定义字体
- 在v$lock里找Holder和Waiter
- python爬取头条视频_Python爬虫:爬取某日头条某瓜视频,有/无水印两种方法
- 防火墙的访问控制策略
- drcom宽带认证登录超时_DrCOM客户端常见问题解决方法
- 数据结构:弗洛伊德算法(最短路径)图文详解
- 大数据学习的第一课-大数据概论和技术原理
- Android 11.0 12.0蓝牙遥控器确认键弹不出输入法的解决方法
热门文章
- 数学除了摧残祖国的花朵外,竟然还可以赢钱!
- 大变天!刚刚,山东突然宣布!关乎800万人...
- 数据库 流量切分_互联网大厂有哪些分库分表的思路和技巧?
- 求职华为,被问观察者模式,从没有这种体验!!!
- 如何讲页面打入jar包中_如何把我的Java程序变成exe文件?
- 计算机网络互联网技术实验报告,2013计算机网络技术与应用.实验报告01
- linux安装rz命令_Linux 安装dep安装包命令
- circle后面是什么意思 python_Ape circle Python操作-第2-01章-列表操作,小猿圈,作业
- java pc计数器_java虚拟机-程序计数器PC Register
- 455. 分发饼干001(贪心算法+详解)