这个难度有点迷,..我就捋一下顺序然后说吧,这个题目难度不是按照T题的日常难度来排的,我就顺便排一下..
暴0不开心 什么时候我能够AK一次呢 qwqq
CCL 的消遣(CCL)
[题目描述]
AS we know,CCL 是一个很无聊很无聊很无聊的人.有一天,CCL 注意到地面上有很多棍子,
于是,CCL 决定用这些棍子来消磨时间(这是要有多无聊啊).
CCL先将这些棍子排成一排.每根棍子有一个长度.CCL一次可以将2个相邻的棍子合并成
一根更长的棍子,合并出的棍子的长度为原来 2 根棍子的长度之和(具体的过程请参考样
例).CCL 想用最少的合并次数来将这些棍子变成一个长度不降的序列.
[输入格式]
输入文件的第一行有一个正整数 n,表示棍子的数目.
接下来一行 n 个正整数,依次表示每根木棍的长度.
[输出格式]
输出文件一行仅一个数,表示最少的合并次数.
[样例输入]
5
8 2 7 3 1
[样例输出]
3
[样例解释]
最优方案是将后 4 根木棍合并,形成一个长度为 13 的棍子,共需要 3 次合并操作.
合并后的序列为:8,13.
[数据范围]
10%的数据,N<=1500
20%的数据,N<=5000
50%的数据,N<=200000
100%的数据,N<=1000000,每根棍子的长度<=maxlongint
暴力过10分.. 那就写正解好了
#define fre yes
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000005;
long long arr[maxn];
long long w[maxn],f[maxn],c[maxn];
long long n,k,ans;
template<typename T>inline void read(T&x)
{
x = 0;char c;int lenp = 1;
do { c = getchar();if(c == '-') lenp = -1; } while(!isdigit(c));
do { x = x * 10 + c - '0';c = getchar(); } while(isdigit(c));
x *= lenp;
}
int main()
{
#ifdef fre
freopen("CCL.in","r",stdin);
freopen("CCL.out","w",stdout);
#endif
memset(f,0x3f3f3f3f,sizeof(f));
read(n);
for (int i=1;i<=n;i++)
{
int x;
read(x);
arr[i] = x;
arr[i] = arr[i-1] + arr[i];
}
long long l = 1,r = 1; f[0] = 0; w[0] = 0;
for (int i=1;i<=n;i++)
{
while(l < r && arr[i] >= f[w[l+1]]) l++;
f[i] = arr[i] - arr[w[l]] + arr[i];
c[i] = c[w[l]] + i - w[l] - 1;
while(r > l && f[i] <= f[w[r]]) r--;
w[++r] = i;
} printf("%lld\n",c[n]);
return 0;
}