2019牛客暑期多校训练营(第七场) - C - Governing sand - 平衡树

5
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5

感觉该出14才对,取前k小写成了取前k大。

5
1 5 4
2 5 3
3 5 2
4 5 1
6 5 5

suf=55 res=0
ans=55
suf=40 res=0
ans=40
suf=30 res=15
ans=40
suf=25 res=25
ans=40
suf=0 res=30
ans=30
30

第四次询问为什么是25?明明要砍完前面所有的9棵树的。擦,curnum加的怎么是c。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int MAXN = 2005;

int ch[MAXN][2];
int val[MAXN], dat[MAXN];
ll siz[MAXN], cnt[MAXN];
ll sum[MAXN];
int tot, root;

inline void Init() {
    tot = 0;
    root = 0;
}

inline int NewNode(int v, ll num) {
    ch[++tot][0] = ch[tot][1] = 0;
    val[tot] = v, dat[tot] = rand();
    siz[tot] = cnt[tot] = num;
    sum[tot] = 1ll * val[tot] * cnt[tot];
    return tot;
}

inline void PushUp(int id) {
    siz[id] = siz[ch[id][0]] + siz[ch[id][1]] + cnt[id];
    sum[id] = sum[ch[id][0]] + sum[ch[id][1]] + 1ll * val[id] * cnt[id];
}

inline void Rotate(int &id, int d) {
    int temp = ch[id][d ^ 1];
    ch[id][d ^ 1] = ch[temp][d];
    ch[temp][d] = id;
    id = temp;
    PushUp(ch[id][d]), PushUp(id);
}

inline void Insert(int &id, int v, ll num) {
    if(!id)
        id = NewNode(v, num);
    else {
        if(v == val[id])
            cnt[id] += num;
        else {
            int d = v < val[id] ? 0 : 1;
            Insert(ch[id][d], v, num);
            if(dat[id] < dat[ch[id][d]])
                Rotate(id, d ^ 1);
        }
        PushUp(id);
    }
}

ll GetSum(int id, ll k) {
    if(!id||k<=0)
        return 0;
    else {
        if(k >= siz[ch[id][0]] + cnt[id])
            return GetSum(ch[id][1], k - siz[ch[id][0]] - cnt[id]) + sum[ch[id][0]] + 1ll * val[id] * cnt[id];
        else if(k >= siz[ch[id][0]])
            return sum[ch[id][0]] + 1ll * val[id] * (k - siz[ch[id][0]]);
        else
            return GetSum(ch[id][0], k);
    }
}

int n;
struct Tree {
    int h, c, p;
    bool operator<(const Tree& t)const {
        return h < t.h;
    }
} tr[100005];

const ll INF = 1e18;

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    while(~scanf("%d", &n)) {
        Init();
        for(int i = 1; i <= n; ++i)
            scanf("%d%d%d", &tr[i].h, &tr[i].c, &tr[i].p);
        sort(tr + 1, tr + 1 + n);
        ll sufcost = 0;
        for(int i = 1; i <= n; ++i)
            sufcost += 1ll * tr[i].c * tr[i].p;
        ll ans = INF;
        for(int i = 1, nxt; i <= n; i = nxt) {
            ll curnum = 0;
            for(nxt = i + 1; nxt <= n && tr[nxt].h == tr[i].h; ++nxt);
            for(int j = i; j < nxt; ++j) {
                curnum += tr[j].p;
                sufcost -= 1ll * tr[j].c * tr[j].p;
            }
            ll res=GetSum(root, siz[root] - curnum + 1);
            ans = min(ans, sufcost + res);
            for(int j = i; j < nxt; ++j)
                Insert(root, tr[j].c, tr[j].p);
        }
        printf("%lld\n", ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/Yinku/p/11326561.html