1. 程式人生 > >【NOIP模擬】指引

【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裡二分,還需要排序,和上面這種硬懟的做法都是nlogn的

孤陋寡聞的鍋。

程式碼

#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; }