用堆来贪心,顺便复习一下左偏树(虽然用不着)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
typedef long long LL;
inline LL read()
{
LL x=0;bool f=0;char c=getchar();
for (;c<'0'||c>'9';c=getchar()) f=c=='-'?1:0;
for (;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
return f?-x:x;
}
const int N=100010;
int n,cnt=0,rt=0,ls[N],rs[N],d[N],val[N],sz=0;
LL ans=0;
struct na
{
int d,p;
}e[N];
inline bool cmp (const na &a,const na &b)
{
return a.d<b.d;
}
int merge(int a,int b)
{
if (!a) return b;
if (!b) return a;
if (val[a]>val[b]) swap(a,b);
rs[a]=merge(rs[a],b);
if (d[ls[a]]<d[rs[a]]) swap(ls[a],rs[a]);
d[a]=d[rs[a]]+1;
return a;
}
inline void push(int x)
{
cnt++;
val[++sz]=x;
rt=merge(rt,sz);
}
inline int pop()
{
cnt--;
int rec=val[rt];
rt=merge(ls[rt],rs[rt]);
return rec;
}
int main()
{
n=read();d[0]=-1;
for (int i=1;i<=n;i++)
e[i].d=read(),e[i].p=read();
sort(e+1,e+n+1,cmp);
for (int i=1;i<=n;i++)
{
if (cnt<e[i].d) ans+=e[i].p,push(e[i].p);
else if (e[i].p>val[rt]) ans+=e[i].p-pop(),push(e[i].p);
}
printf("%lld\n",ans);
return 0;
}