题意:
给定n个旅馆的p和d两个属性,然后输出所有的目的旅馆。如果对于所有的旅馆i来说,没有其他任何一个旅馆的px和dx值同时小于pi和di。那么旅馆i可以算作一个是“目的旅馆”。
题解:
这个题和蓝书P228相似,但是好难用画图法转化,转化了半天也没转化对。
这里的解法是将二维转化为一维,定义数组a[p]=d 表示所有价格为p的旅馆中最小d。然后根据a数组转化为RMQ,初始化数组。
线性扫描一遍所有旅馆,每次从(1,p-1)找最小的d = d_min,如果当前旅馆的d满足 d<=d_min,则可以认为当前旅馆为目标旅馆(反过来就存在旅馆p和d同时小于当前旅馆了。所以不是目的旅馆)。
include<bits/stdc++.h>
using namespace std;
const int maxn = 10011;
int a[maxn];
int dmin[maxn][20];
void initmin(int n,int d[])
{
for(int i=0;i<=n;i++)dmin[i][0]=d[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dmin[i][j] = min(dmin[i][j-1],dmin[i+(1<<(j-1))][j-1]);
}
int getmin(int l,int r)
{
int k=0;
while(1<<(k+1)<=r-l+1)k++;
return min(dmin[l][k],dmin[r-(1<<k)+1][k]);
}
struct node
{
int p,d;
bool operator <(const node& a)const
{
if(p==a.p)
return d<a.d;
return p<a.p;
}
}ns1[maxn],ns2[maxn];
int main()
{
int n;
while(cin>>n)
{
fill(a,a+maxn,0x3f3f3f3f);
for(int i=1;i<=n;i++)
{
int p,d;
scanf("%d%d",&p,&d);
p++,d++;
ns1[i].p=p;
ns1[i].d=d;
a[p]=min(a[p],d);
}
initmin(maxn,a);
int cnt=0;
for(int i=1;i<=n;i++)
{
int p,d;
p = ns1[i].p;
d = ns1[i].d;
if(p==1)
{
ns2[++cnt]=ns1[i];
}
else
{
int d_min = getmin(1,p-1);
if(d<=d_min)///不能dmin比d小了。
ns2[++cnt]=ns1[i];
}
}
sort(ns2+1,ns2+1+cnt);
cout<<cnt<<endl;
for(int i=1;i<=cnt;i++)
printf("%d %d\n",ns2[i].p-1,ns2[i].d-1);
}
}