算法分析
树状数组上二分
只要截至日期前的任务数量小于截至日期那么就全都可以做完
截止日期前的任务数大于截止日期时,就按照贪心(权重大的)尽可能往后放着,直至塞不进就行
那么就是二分在某个截至日期能塞的最后的位置就可以了
AC Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
int n,tr[N];
struct node
{
int t,w;
}a[N];
bool cmp(node a,node b)
{
return a.w > b.w;
}
int lowbit(int x)
{
return x & -x;
}
void update(int pos,int v)
{
while(pos <= n)
{
tr[pos] += v;
pos += lowbit(pos);
}
}
ll query(int pos)
{
ll res = 0;
while(pos)
{
res += tr[pos];
pos -= lowbit(pos);
}
return res;
}
int main()
{
cin >> n;
for(int i = 1;i <= n;i ++)
{
scanf("%d%d",&a[i].t,&a[i].w);
a[i].t = min(a[i].t,(int)1e5);
}
sort(a + 1,a + 1 + n,cmp);
ll ans = 0;
for(int i = 1;i <= n;i ++)
{
if(query(a[i].t) < a[i].t)
{
int l = 1,r = n,res;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(query(a[i].t) - query(mid - 1) < a[i].t - mid + 1)
{
l = mid;
}
else r = mid - 1;
}
update(l,1);
ans += a[i].w;
}
}
printf("%lld\n",ans);
return 0;
}