_mi_ka_
2024-11-19 20:41:09
是漂亮的玛拉妮耶!!!
在数轴
考虑贪心:从前往后走的时候,如果遇到障碍物,则从当前遇到的所有道具里面选尽量大的肯定最优,因为这样能使得选的道具尽量少。
基于以上贪心,考虑用优先队列大根堆存下当前所遇到的所有增强道具,每遇到障碍物,从大往小选,直到当前的跳跃能力能够跳过当前障碍物(即如果障碍物的长度为
3\le L\le 10^9
由于当前的数轴长度
离散化时间复杂度
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#define N 400005//注意离散化数组范围
using namespace std;
int T,n,m,L,cnt;
struct obs//obstacle 障碍物
{
int l,r,len;
}o[N];
struct tols//tools 增强道具
{
int x,v;
}t[N];
int bok[N],bl[N];//离散化数组
priority_queue<int>q;//默认大根堆
int re()//防止作弊不放快读快写
void wr(int x)
signed main()
{
T=re();
while(T--)
{
n=re(),m=re(),L=re();
cnt=0;
for(int i=1;i<=n;i++)
{
o[i].l=re(),o[i].r=re();
o[i].len=o[i].r-o[i].l+1;
bok[++cnt]=o[i].l;//离散化左端点
}
for(int i=1;i<=m;i++)
{
t[i].x=re(),t[i].v=re();
bok[++cnt]=t[i].x;//离散化道具位置
}
sort(bok+1,bok+cnt+1);
int boks=unique(bok+1,bok+cnt+1)-bok-1;
for(int i=1;i<=n;i++)
o[i].l=lower_bound(bok+1,bok+boks+1,o[i].l)-bok;
for(int i=1;i<=m;i++)
t[i].x=lower_bound(bok+1,bok+boks+1,t[i].x)-bok;//朴素的离散化
int nowo=0,nowt=0,ans=0,nowv=1,flag=0;
//当前第几个障碍物,第几个道具,当前答案(捡的道具个数),当前跳跃能力,是否中途因跳跃能力不够而直接输出 -1
for(int i=1;i<=boks;i++)//遍历离散化后的位置
{
while(i==t[nowt+1].x&&nowt<m)//下个位置有道具
{
nowt++;
q.push(t[nowt].v);//存入优先队列
}
if(i==o[nowo+1].l&&nowo<n)//下个位置有障碍
{
nowo++;
int bas=o[nowo].len;
while(q.size()!=0&&nowv<=bas)//拿道具
{
nowv+=q.top();
q.pop(),ans++;
}
if(!q.size()&&nowv<=bas)//道具拿满也不够跳过障碍
{
puts("-1");
flag=1;
break;
}
}
}
while(q.size())
q.pop();//多测清空
if(!flag)
wr(ans),putchar('\n');
}
return 0;
}