专栏文章
题解:P14078 [GESP202509 七级] 金币收集
P14078题解参与者 6已保存评论 7
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 7 条
- 当前快照
- 1 份
- 快照标识符
- @minqo7d5
- 此快照首次捕获于
- 2025/12/02 06:46 3 个月前
- 此快照最后确认于
- 2025/12/02 06:46 3 个月前
题解:P14078 [GESP202509 七级] 金币收集
题外话
我用伪 的做法在 GESP 考场上喜提 22.5 分,但在洛谷上提交居然得了满分。居然这道题是一道绿题,有点惊讶。毕竟我的做法是贪心,感觉最多只值黄题难度。差点就场切绿题了。
思路
我们需要刚好在第 秒如果在 的坐标就可以吃到这个金币,首先因为我们只能从左往右走,所以我们会想到按照 坐标来进行排序,此时我们走到那儿时如果之前从没有原地不动会发现我们还需要等待 时间吃到该金币,所以在我们等到那个时间时我们会浪费掉 的时间,所以有些金币在等待后是吃不到了。那我们需要预处理每个金币在等待多久之后吃不到了,很简单,那就是拿一个数组 存储 即可。我们想吃到更多的金币那就找 的最长上升子序列,因为我从前往后每个金币都保证一个金币浪费的时间永远会影响到后面的金币。
小提示:
- 当 相同时需要按照 从小往大排序。不然 相同时前面的 会影响到后面的 。
- 注意 的情况。
- 最长上升子序列需要用二分优化到可以实现 做法。
code
CPP#include<bits/stdc++.h>
using namespace std;
#define int long long
struct pp{
int a,b;
}a[230000];
int p[230000],f[230000];
int cmp(pp ap,pp bp){
if(ap.a==bp.a){
return ap.b<bp.b;
}
return ap.a<bp.a;
}//排序
signed main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].a>>a[i].b;
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
if(a[i].a>a[i].b){
p[i]=1e12;
}//注意时间小于坐标
else{
p[i]=a[i].b-a[i].a;
}
}
//最长上升子序列
f[1]=p[1];
int q=1;
if(p[1]==1e12){
f[1]=0;
q=0;
}
for(int i=2;i<=n;i++){
if(p[i]==1e12){
continue;
}
int l=1,r=q,ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(f[mid]>p[i]){
r=mid-1;
ans=mid;
}
else{
l=mid+1;
}
}
if(ans==-1){
q++;
f[q]=p[i];
}
else{
f[ans]=p[i];
}
}
cout<<q;
return 0;
}
相关推荐
评论
共 7 条评论,欢迎与作者交流。
正在加载评论...