(AtCoder Beginner Contest 225 E 斜率区间离散化 求最大不相交区间

73 篇文章 2 订阅
46 篇文章 2 订阅

题目

在第一象限
给你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 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值