Arthur and Table 【CodeForces - 557C】【Splay】

题目链接


有一张桌子,有n个腿。第i根腿的长度是li。

现在要拿掉一些腿,使得桌子稳定,拿掉第i根腿需要di的能量。

稳定的条件是,假如拿掉若干条腿之后,桌子还有k个腿,那么长度最长的腿的数目要超过一半。比如桌子有5根腿,那么至少要有三根腿是最长的。另外,只有一根腿的桌子是稳定的,两个腿的桌子想要稳定,必需长度是一样的。

你的任务是拿掉若干腿,使得桌子稳定,并且所消耗的能量要最少。


  然后,我们可以枚举是哪个“高度”最为这个最高高度。

  那么,高于这个最高高度的,就必须要减去了的,然后在剩下部分,我们可能还要减去一些点,使得这个高度超过一半,我们肯定减去的是最小的部分,所以用Splay充当一个堆来维护前K小。

跑起来真快,78ms。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f3f3f3f3f
#define eps 1e-8
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
int N, root = 0, tot = 0, L[maxN], D[maxN], _UP = 0, sz[maxN] = {0};
ll ss[maxN] = {0};
vector<int> vt[maxN];
struct node
{
    int ff, val, num, siz, ch[2]; ll sum;
    node() { ff = val = siz = ch[0] = ch[1] = num = sum = 0; }
} t[maxN<<2];
void pushup(int rt)
{
    t[rt].siz = t[t[rt].ch[0]].siz + t[t[rt].ch[1]].siz + t[rt].num;
    t[rt].sum = t[t[rt].ch[0]].sum + t[t[rt].ch[1]].sum + 1LL * t[rt].val * t[rt].num;
}
void Rotate(int x)
{
    int y = t[x].ff, z = t[y].ff;
    int k = t[y].ch[1] == x;
    t[z].ch[t[z].ch[1] == y] = x;
    t[x].ff = z;
    t[y].ch[k] = t[x].ch[k ^ 1];
    t[t[x].ch[k ^ 1]].ff = y;
    t[x].ch[k ^ 1] = y;
    t[y].ff = x;
    pushup(y);  pushup(x);
}
inline void Splay(int x, int goal)
{
    while(t[x].ff != goal)
    {
        int y = t[x].ff, z = t[y].ff;
        if(z != goal) (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? Rotate(x) : Rotate(y);
        Rotate(x);
    }
    if(!goal) root = x;
}
void Insert(int x)
{
    int u = root, ff = 0;
    while(u && (t[u].val ^ x))
    {
        ff = u;
        u = t[u].ch[x > t[u].val];
    }
    if(u)
    {
        t[u].num ++;
    }
    else
    {
        u = ++tot;
        if(ff) t[ff].ch[x > t[ff].val] = u;
        t[u].num = 1;
        t[u].ff = ff;
        t[u].val = x;
        t[u].siz = 1;
    }
    Splay(u, 0);
}
ll sum_K(int kth)
{
    int u = root; ll ans = 0;
    while(true)
    {
        int y = t[u].ch[0];
        if(kth > t[y].siz + t[u].num)
        {
            kth -= t[y].siz + t[u].num;
            ans += t[y].sum + 1LL * t[u].num * t[u].val;
            u = t[u].ch[1];
        }
        else
        {
            if(t[y].siz >= kth) u = y;
            else
            {
                ans += t[y].sum + 1LL * (kth - t[y].siz) * t[u].val;
                break;
            }
        }
    }
    return ans;
}
int main()
{
    scanf("%d", &N);
    for(int i=1; i<=N; i++) { scanf("%d", &L[i]); _UP = max(_UP, L[i]); }
    for(int i=1; i<=N; i++) scanf("%d", &D[i]);
    for(int i=1; i<=N; i++) vt[L[i]].push_back(D[i]);
    for(int i=1, len; i<=_UP; i++)
    {
        len = (int)vt[i].size();
        ss[i] = ss[i - 1]; sz[i] = sz[i - 1] + len;
        for(int j=0; j<len; j++) ss[i] += vt[i][j];
    }
    ll ans = INF, tmp;
    for(int i=1, len, need_del; i<=_UP; i++)
    {
        len = (int)vt[i].size();
        if(!len) continue;
        tmp = ss[_UP] - ss[i];
        need_del = sz[i] - 2 * len + 1;
        if(need_del > 0)
        {
            tmp += sum_K(need_del);
        }
        ans = min(ans, tmp);
        for(int j=0; j<len; j++) Insert(vt[i][j]);
    }
    printf("%lld\n", ans);
    return 0;
}
发布了893 篇原创文章 · 获赞 1069 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_41730082/article/details/105316377