【NOIP模拟】指引
题面
N 名迷途的旅者需要小 X 的指引。
初始时,每一名旅者 i 位于坐标(Ai,Bi)处,旅者们只能够向右或是向上移动.
也就是说,他们只能够增加自己的某一维坐标,而不能减小它们。
这片大地上同样存在者 N 个出口,每一个出口 i 位于坐标(Ci,Di)处,一个出一旦被某个旅者通过,它们就会一并消失。
请帮助小 X 计算他至多能够指引多少旅者离开这片大地。
n<=105
分析
按x升序排序贪心一波,对于每个出口,把它右边的人全部加进来,然后选择y比它小但y最大的那个。
就是这个操作,我思考到底用什么数据结构维护。
恕我孤陋寡闻,不知道set是可以lower_bound。我就只能用优先队列硬怼,每次把怼出来的但是比现在这个高度大的先放一个vector里存一下。
while(!q.empty()) { pii tmp=q.top();q.pop(); if(tmp.first<=ex[i].y){ans++;break;} v.push_back(tmp); } if(!v.empty()) for(int j=0;j<v.size();j++)q.push(v[j]); while(!v.empty())v.pop_back();
我是真的想了lower_bound的,对天发誓!但是如果直接vector里二分,还需要排序,和上面这种硬怼的做法都是n2logn的
孤陋寡闻的锅。
代码
#include<bits/stdc++.h> using namespace std; #define N 100010 int n,l=1,num,ans,cnt,now=1; struct email { int x,y,id; }a[N],b[N],c[N],d[N],ex[N]; set<int>s; template<class T> inline void read(T &x) { x=0;int f=1;static char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} x*=f; } bool cmp1(email a,email b){return a.x<b.x;} int main() { for(int i=1;i<=n;i++)read(a[i].x),read(a[i].y),a[i].id=i; for(int i=1;i<=n;i++)read(b[i].x),read(b[i].y); for(int i=1;i<=n;i++)c[i]=a[i],d[i]=b[i]; sort(c+1,c+1+n,cmp1);sort(d+1,d+1+n,cmp1); while(d[l].x<c[1].x)l++; for(int i=l;i<=n;i++)ex[++cnt]=d[i]; sort(ex+1,ex+1+cnt,cmp1);sort(a+1,a+1+n,cmp1); for(int i=1;i<=cnt;i++) { while(now<=n&&ex[i].x>=a[now].x)s.insert(a[now].y),now++; set <int> :: iterator tmp=s.lower_bound(ex[i].y); if(tmp==s.begin())continue; tmp--;ans++;s.erase(tmp); } printf("%d\n",ans); return 0; }
“Make my parents proud,and impress the girl I like.”