题目链接
有一张桌子,有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;
}