题目大意
平面上有$N$堆砖。
搬砖工王修涵每次会合并相邻的两堆砖。
因为他比较蠢,所以他会把两堆砖往中间摞一起。也就是说代价是两堆砖的块数之和。
他想知道把所有石子合并到一起的最小总代价是多少。否则输出$-1$。
题目分析
裸题。
见这里。
需要小卡一波常数。
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| #include<iostream> #include<cstdio> using namespace std;
typedef long long LL;
namespace FastIO { const int L=1<<15; char buf[L],*S,*T; char getchar() { if(S==T) {T=(S=buf)+fread(buf,1,L,stdin);if(S==T)return EOF;} return *S++; } int Get_Int() { int res=0,bj=1;char c=getchar(); while(!isdigit(c)) {if(c=='-')bj=-1;c=getchar();} while(isdigit(c)) {res=res*10+c-'0';c=getchar();} return res*bj; } } using FastIO::Get_Int;
const int maxn=100005;
int n,cnt; LL ans=0,a[maxn];
void Combine(int k) { LL tmp=a[k-1]+a[k]; ans+=tmp; for(int i=k; i<=cnt; ++i)a[i]=a[i+1]; --cnt; int j=1; for(j=k-1; a[j-1]<tmp&&j>1; --j)a[j]=a[j-1]; a[j]=tmp; int delta; while(a[j]>=a[j-2]&&j>=3) { delta=cnt-j; Combine(j-1); j=cnt-delta; } }
int main() { n=Get_Int(); for(int i=1; i<=n; ++i)a[i]=Get_Int(); cnt=1; for(int i=2; i<=n; ++i) { a[++cnt]=a[i]; while(a[cnt-2]<=a[cnt]&&cnt>=3)Combine(cnt-1); } while(cnt>=2)Combine(cnt); printf("%lld\n",ans); return 0; }
|