下雪了,小 Y 堆了 n n n 个雪柱排成一排,调皮的小 X 打算推倒这 n n n 个雪柱,他想在最少的时间内推倒所有雪柱,于是他请你来为他出谋划策。
小 Y 堆的每个雪柱高 a i a_i ai 单位,推倒一个雪柱的时间为该雪柱的高度。小 X 只能从这一排雪柱的两端推雪柱 *,次数不限,小 X 移动的时间可以忽略不计。这样就可以使一个雪柱倒向其他雪柱,从而击倒另一个雪柱(击倒的时间忽略不计),然后发生连锁反应,更加节省时间 **。
设初始的势能为当前手动推倒的雪柱 k k k 的高度 p = a k p=a_k p=ak,则此轮连锁反应中第 i i i 个雪柱倒向第 j j j 个雪柱时:
请你求出推倒所有雪柱的最短时间。
*:每一次要么从左边推最左边的雪柱,要么从右边推最右边的雪柱。
**:雪柱的倒塌方向取决于推雪柱的方向,如果从左边推,雪柱就会向右依次倒塌(第 i i i 个雪柱倒塌向第 i + 1 i+1 i+1 个雪柱),反之同理。
本题有多组测试数据。
第一行一个整数 T T T,表示数据组数。
对于每组数据:
第一行一个整数 n n n,表示雪柱的数量。
第二行 n n n 个整数,分别表示每个雪柱的高度。
对于每组数据:输出一行一个整数,表示推倒所有雪柱的最短时间。
3
5
2 3 1 4 5
6
6 6 6 6 6 6
6
1 1 4 5 1 4
7
6
8
第一次从左边推,耗费 2 2 2 点时间,使得 5 5 5 个雪柱 的高度分别变为: 0 , 1 , 1 , 4 , 5 0,1,1,4,5 0,1,1,4,5。
第二次从右边推,耗费 5 5 5 点时间,使得所有雪柱都被击倒。
共耗费 7 7 7 点时间。
从左边或者右边都可以一次性推完,共耗费 6 6 6 点时间。
第一次从右边推,耗费 4 4 4 点时间,使得 6 6 6 个雪柱的高度分别变为: 1 , 1 , 4 , 4 , 0 , 0 1,1,4,4,0,0 1,1,4,4,0,0。
第二次从右边推,耗费 4 4 4 点时间,使得所有雪柱都被击倒。
共耗费 8 8 8 点时间。
本题采用捆绑测试。
Subtask \text{Subtask} Subtask | 分值 | n ≤ n \le n≤ |
---|---|---|
0 0 0 | 10 10 10 | 20 20 20 |
1 1 1 | 15 15 15 | 100 100 100 |
2 2 2 | 25 25 25 | 1000 1000 1000 |
3 3 3 | 50 50 50 | 1 0 5 10^5 105 |
对于全部数据,保证: 1 ≤ T ≤ 10 1 \le T \le 10 1≤T≤10, 1 ≤ n ≤ 1 0 5 1 \le n \le 10^5 1≤n≤105, 1 ≤ a i ≤ 1 0 10 1 \le a_i \le 10^{10} 1≤ai≤1010。
我们可以暴力的枚举一下往左推和往右推得到的结果。最终综合一下即可。
那具体怎么写呢?
//直接模拟
#include
#include
#include
#define int long long
using namespace std;
const int N = 1e5+10;
int w[N];
int d1[N],l1[N];
int d2[N],l2[N];
int n,T;
int ans;
signed main(){
cin>>T;
while(T--){
memset(d1,0,sizeof d1);
memset(d2,0,sizeof d2);
memset(l1,0,sizeof l1);
memset(l2,0,sizeof l2);
ans=1e18;
cin>>n;
for(int i=1;i<=n;i++)cin>>w[i];
//往左推
for(int i=1;i<=n;i++){
d1[i]=d1[i-1];
if(l1[i-1]==0)d1[i]+=w[i],l1[i]=w[i];//若前一个雪柱被完全推倒,则当前雪柱独立推倒
else if(l1[i-1]>=w[i])l1[i]=w[i];//若前一个雪柱未倒下且足够的势能推倒当前雪柱
else{
l1[i]=w[i]-l1[i-1],d1[i]+=(w[i]-l1[i-1]);// 若前一个雪柱部分倒下,计算当前雪柱被推倒的势能
}
}
//从右推
for(int i=n;i>=1;i--){
d2[i]=d2[i+1];
if(l2[i+1]==0)d2[i]+=w[i],l2[i]=w[i];
else if(l2[i+1]>=w[i])l2[i]=w[i];
else{
l2[i]=w[i]-l2[i+1],d2[i]+=(w[i]-l2[i+1]);
}
}
for(int i=1;i<=n;i++)ans=min(ans,d1[i-1]+d2[i+1]+max(0ll,w[i]-(l1[i-1]+l2[i+1])));
cout<