SCUT - 131 - P small to play the game II - greed - balanced tree

https://scut.online/p/131

First, if a handpicked group of people to play the monster, you can put the main task of who threw the biggest b play, so not worse. Then consider this b enumerate the largest, other people sparring. Beginning ai + k * bi + sumC-ci, this is well understood, then that person is separated at most t = k-1 Ge monster to fight sparring group, then the group since the provisions of sparring each person can only choose one to play , then it is surely greedy selected vj = aj + t bj-cj largest individual play. It puts Treap (casual, but a lot of hair WA) to maintain it.

Note that this template I actually did not initialize, grass, even write their own. But Treap specific principle is not very clear.

Note that WA does not exceed k point is to find individuals, and v is greater than the pile and bi. When the right subtree is empty does not mean you can quit, or when there are now entering the second classification, it is possible here subtrees is useful.

See someone looking directly dichotomy, the heart is one thousand mud horse. Well when you learn about a balanced tree.

Note To open the double space because there are twice insert. Unless you get hold of the recovery? Recovered well to do, a little bit of space measured omitted. Because there is a maximum of n points simultaneously through direct intuition so this can be: put forward a STLstack (can not use an array of otherwise not waste your face?) Newnode when removed from the stack inside, remove the id back in time to stack inside.

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

const int MAXN = 200000;

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

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

inline int NewNode(int v) {
    ch[++tot][0] = 0;
    ch[tot][1] = 0;
    val[tot] = v, dat[tot] = rand();
    siz[tot] = 1, cnt[tot] = 1;
    sum[tot] = v;
    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) {
    if(!id)
        id = NewNode(v);
    else {
        if(v == val[id])
            ++cnt[id];
        else {
            int d = v < val[id] ? 0 : 1;
            Insert(ch[id][d], v);
            if(dat[id] < dat[ch[id][d]])
                Rotate(id, d ^ 1);
        }
        PushUp(id);
    }
}

void Remove(int &id, int v) {
    if(!id)
        return;
    else {
        if(v == val[id]) {
            if(cnt[id] > 1) {
                cnt[id]--;
                PushUp(id);
            } else if(ch[id][0] || ch[id][1]) {
                if(!ch[id][1] || dat[ch[id][0]] > dat[ch[id][1]])
                    Rotate(id, 1), Remove(ch[id][1], v);
                else
                    Rotate(id, 0), Remove(ch[id][0], v);
                PushUp(id);
            } else
                id = 0;
        } else {
            v < val[id] ? Remove(ch[id][0], v) : Remove(ch[id][1], v);
            PushUp(id);
        }
    }
}

ll GetSum(int bi, int k) {
    if(k == 0)
        return 0;
    //把大于bi的最大的至多k个v全部加起来,每加一个减去一个bi
    int r = root;
    ll res = 0;
    while(r) {
        if(bi >= val[r] || (ch[r][1] && siz[ch[r][1]] >= k)) {
            //bi不比这个节点小,这个节点没用,向右走
            //或者前k大完全在右子树中
            r = ch[r][1];
            continue;
        } else {
            //有用的完全在该节点及其右子树中
            /*if(!ch[r][1])
                return res;*/
            res += sum[ch[r][1]];
            res -= 1ll * siz[ch[r][1]] * bi;
            k -= siz[ch[r][1]];
            if(k <= cnt[r]) {
                res += 1ll * k * (val[r] - bi);
                k = 0;
                return res;
            }
            else{
                res += 1ll * cnt[r] * (val[r] - bi);
                k -=cnt[r];
            }
            r=ch[r][0];
        }
    }
    return res;
}

int n, k;
struct Char {
    int a, b, c;
    int v;
    Char() {};
    Char(int _a, int _b, int _c) {
        a = _a;
        b = _b;
        c = _c;
        v = a + b - c;
    }
} cha[100005];

ll sumC;

ll calc(int id) {
    ll M = sumC - cha[id].c + cha[id].a + 1ll * k * cha[id].b  ;
    Remove(root, cha[id].v);
    //至多从平衡树拿走k-1个
    ll res = GetSum(cha[id].b, k - 1);
    Insert(root, cha[id].v);
    return M + res;
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &k);
        sumC = 0;
        Init();
        for(int i = 1; i <= n; ++i) {
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            cha[i] = Char(a, b, c);
            sumC += c;
            Insert(root, cha[i].v);
        }
        ll ans = 0;
        for(int i = 1; i <= n; ++i)
            ans = max(ans, calc(i));
        printf("%lld\n", ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Yinku/p/11324839.html