uva 11020 Efficient Solutions(multiset)
题意:给出n个人的属性(a,b),当A(a,b)与B(a',b')存在关系:(a<a'&&b<=b')||(a<=a'&&b<b')就说A比B占优势,否则,两人都存在优势。问:每输入一个人的信息,计算当前占优势的人的个数。
分析:容易想到以坐标形式在一个平面图上表示每个人的信息,那么以上的条件关系式就转变为,当一个点的左下方(可以是正左、正下)有一个点,那么该点失去优势。关键是明确当一个点失去优势后,就不再可能重新获得优势。那么只要维护所有有优势的人群即可——选择一个合适的数据结构。
我们选择multiset(可重集)来处理,这里要注意的是存在属性完全相同的两个人。这里使用multiset,是利用它自动排序和可重两个特点。当把一个人(x1,y1)加入集合,只要与其左侧(x2<x1||(x2==x1&&y2<y1))作比较,就可以判断是否有优势;若加入集合,只要向右(x2>x1)查找,所有(y2>y1)的点(x2,y2)都失去优势,从集合中删除。
注意:若左侧没有点it==s.begin(),必然可以加入。
1 #include<cstdio> 2 #include<set> 3 using namespace std; 4 5 struct P{ 6 int x,y; 7 bool operator < (const P& rhs)const { 8 return x<rhs.x||(x==rhs.x&&y<rhs.y); 9 } 10 }; 11 12 multiset<P>s; 13 multiset<P>::iterator it; 14 15 int main() 16 { 17 int T,n; 18 scanf("%d",&T); 19 for(int k=1;k<=T;k++) 20 { 21 if(k!=1)puts(""); 22 printf("Case #%d:\n",k); 23 s.clear(); 24 25 scanf("%d",&n); 26 while(n--) 27 { 28 int x,y; 29 scanf("%d%d",&x,&y); 30 P e=(P){x,y}; 31 it=s.lower_bound(e); 32 if(it==s.begin()||(--it)->y>y){ 33 s.insert(e); 34 it=s.upper_bound(e); 35 while(it!=s.end()&&it->y>=y){ 36 s.erase(it++); 37 } 38 } 39 printf("%d\n",s.size()); 40 } 41 } 42 return 0; 43 }