题目
在第一象限
给你N个 “ 7 ” (即由 (x-1,y) (x,y) (x,y-1)构成的7字型 )的x , y 。
要求删除一部分的7,使得从原点看可以看到尽可能多的7 。
链接
题解思路
难点在于根据题目意思抽象出区间,以及区间离散化 。
画图可以知道,每个7带来的影响就是两个斜率((x-1,y) 和 (x,y-1) 分别与原点构成的斜率 )包含的7不能被看到了。
这样我们将每个7的两个斜率化为区间,左右,再根据求最大不相交区间的方法就可以过了。
但是斜率由于精度会变得非常难处理(趋于正无穷少精度爆doule等等)。
我们如果要求最大不相交区间,只需每个端点的相对关系。
这样,我们就可以将每个斜率离散化。
化除法为乘法。排序出相对大小并用map记录。
然后将离散化后的斜率值作为端点值放入区间,求最大不相交区间。
最大不相交区间应该是很久之前学的,杭电那道暑假不ac就很经典。
但是我居然记错了。
将右端点从小到打排序,在基础上将左端点从小到大。
不断往前贪心就是答案。
用y总的比较法可以证出来。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int ,int >
using namespace std;
const int INF = 0x3f3f3f3f;
struct node {
int x, y;
node(int xx, int yy) {x = xx; y = yy;}
bool operator<(const node& b) const {
return 1ll * b.y * x < 1ll * b.x * y;
}
};
vector < node > a ;
vector < node > h ;
map < node , int > mp ;
vector < PII > v ;
bool cmp ( PII A , PII B )
{
if ( A.second == B.second )
return A.first < B.first ;
return A.second < B.second ;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);
int n ;
cin >> n ;
for (int i = 0 ; i < n ; i++ )
{
int t1 ,t2 ;
cin >> t1 >> t2 ;
a.push_back({ t1 -1 , t2 } ) ;
h.push_back({ t1 -1 , t2 } ) ;
a.push_back({ t1 , t2 - 1 } ) ;
h.push_back({ t1 , t2 - 1 } ) ;
}
sort( h.begin() , h.end() ) ;
int cnt = 1 ;
for (int i = 0 ; i < h.size() ; i++ )
{
if (mp.count(h[i]))
continue ;
mp[h[i]] = cnt ;
cnt ++ ;
}
for (int i = 0 ; i < n ; i++ )
{
v.push_back( { mp[ a[i << 1 ] ] , mp[ a[ i << 1| 1] ] } ) ;
}
sort (v.begin() , v.end() , cmp ) ;
int p = 0 ;
int ans = 1 ;
for (int i = 0 ; i < v.size() ; i++ )
{
if (v[i].first >= v[p].second )
{
ans ++ ;
p = i ;
}
}
cout << ans << "\n" ;
return 0 ;
}