每次合并最小的两堆就行了,自己觉得是用的线段树,不过yiyi说这是RMQ。
AC代码:
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <assert.h> #include <algorithm> #define MAX 1234567890 #define MIN -1234567890 #define eps 1e-8 using namespace std; const int maxn = 10010; long long sum[maxn<<2]; void pushup(int rt) { if(sum[rt<<1] == -1) sum[rt] = sum[rt<<1|1]; else if(sum[rt<<1|1] == -1) sum[rt] = sum[rt<<1]; else sum[rt] = min(sum[rt<<1], sum[rt<<1|1]); } void build(int l, int r, int rt) { if(l == r) { scanf("%d", &sum[rt]); return ; } int m = (l + r) >> 1; build(l, m, rt<<1); build(m+1, r, rt<<1|1); pushup(rt); } void update(int p, int rep, int l, int r, int rt) { if(l == r) { sum[rt] = rep; return ; } int m = (l + r) >> 1; if(p <= m) update(p, rep, l, m, rt<<1); else update(p, rep, m+1, r, rt<<1|1); pushup(rt); } int query(int x, int l, int r, int rt) { if(l == r) return l; int m = (l + r) >> 1; if(x == sum[rt<<1]) return query(x, l, m, rt<<1); else return query(x, m+1, r, rt<<1|1); } int main() { #ifdef BellWind freopen("10372.in", "r", stdin); #endif // BellWind int n; while(~scanf("%d", &n)) { long long ans = 0; build(1, n, 1); int pos; for(int i = 1; i < n; i++) { int h1 = sum[1]; ans += h1; pos = query(h1, 1, n, 1); update(pos, -1, 1, n, 1); int h2 = sum[1]; ans += h2; pos = query(h2, 1, n, 1); update(pos, h1+h2, 1, n, 1); } printf("%lld\n", ans); } return 0; }