tokitsukaze and Soldier
tokitsukaze and Soldier
https://ac.nowcoder.com/acm/problem/50439
Emmmm,昨天的每日一题,也是看了题解才会的(手动狗头)。
虽然我的想法接近了一些,但是很明显给T了,枚举暴力,的确太LOW了。我是这么想的,先按照一个s的顺序把这列数字给排好,然后依次进行枚举,往后进行叠加,找出最大值,现在仔细想想,好像的确错了,也可能前面的数v也比较大。但是数据居然过了样例(10%)居然迷惑我(再次狗头)
好吧,上题解。
题解呢,是先将这串数按着s的值从大到小进行排序,然后呢,往后依次加进一个优先队列里头(这个优先队列是一个最小堆)然后因为是按照s的大小排序,所以前面加进队列的数字一定会能够待在这个队列里头,现在就是检验后面加进队列的数,相应的cnt也加着,是否满足v小于等于这个队列size的条件,满足next,否则呢,就把比较小的数踢出队列,这样得到的cnt的值能够尽可能的大,每一次加和之后都进行一次求最大值,因为可能存在后面的数v比较小的情况。差不多就是这样了。
```
Day Day Up.
```#include<iostream>
#include<cstdio>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
struct node{
ll s,v;
}num[N];
bool cmp(node a,node b)
{
return a.s>b.s;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d%d",&num[i].v,&num[i].s);
sort(num,num+n,cmp);
priority_queue<ll,vector<ll>,greater<ll>>q;//一个最小堆,队首是一个最小的属性值,这样相加的时候就会去除掉最小的元素。
ll cnt=0,ans=0;
for(int i=0;i<n;i++)
{
cnt+=num[i].v;
q.push(num[i].v);
while(q.size()>num[i].s)//因为是按照一个特定的顺序排好的,如果后面的那个数字较小的过了的话,则前面的也过了,否则的话就是过不了。然后进行删减前面的数字得到的就是能够排的最多的数。
{
cnt-=q.top();
q.pop();
}
ans=max(cnt,ans);
}
printf("%lld\n",ans);
return 0;
}//偷来的代码</ll></ll></algorithm></cstdio></iostream>