题意:
给定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);}}