刚看以为是一道DP,但是分析发现,我们其实不需要状态转移,我们很容易发现这题取最优结果的状态,找到这个状态直接计算即可
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 110;
#define int long long
signed main()
{
int T;
cin>>T;
while(T--)
{
int pre[N]={0},k[N]={0},h[N]={0};
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>k[i];
for(int i=1;i<=n;i++)cin>>h[i];
//预处理出来到达i位置时最小的攻击力
for(int i=n-1;i>=1;i--)h[i]=max(h[i],h[i+1]+k[i]-k[i+1]);
int res=0;
//贪心思想
for(int i=1;i<=n;i++)
{
//如果i-1到i这个区间攻击力可以从1增加到h[i]则直接计算,如果时间区间不够用,则需要从i-1位置的攻击力一直加到i位置
if(h[i]>k[i]-k[i-1])
{
int t=pre[i-1]+k[i]-k[i-1];
pre[i]=t;
res+=t*(t+1)/2-(pre[i-1]*(pre[i-1]+1))/2;
}
else
{
res+=h[i]*(h[i]+1)/2;
pre[i]=h[i];
}
}
cout<<res<<endl;
}
}