小奇画图(UPC)

/*

该思想由博文提出,我整理了一下,并用优先队列优化了一下实现。

将所有线段按照左端点升序、右端点升序排列。

每次查找两个线段k1 k2 ,如果他们的左端点相同,那如果以两个线段的右端点为端点的线段存在,平面数++;

如果左端点不相同,那即 k2.left==k1.right 也不需要判断是否存在k1.left到k2.right的线段,因为他们是按左端点升序遍历的,

如果存在的话也已经在上一步的到计算了。

还有一个很重要的问题,如果一个线段是由两个以上的小线段组成的话,只按照上诉遍历会漏掉。


___1____        _____3______
            
       ____2____

___________4________________


如图,先计算1和4,发现没有1的右端点到4的右端点的线段,这时我们可以把4等效成为从1的右端点到4的右端点的线段,
塞回优先队列中,不妨记为5号线段。根据左端点升序,接下来我们比较2和5,发现存在2.right到5.right的线段,即3,所以平面数++.


*/

#include <bits/stdc++.h>
using namespace std;

struct k{
    int a,b;
    bool operator < (const k & y)const{
        if (a==y.a) return b>y.b;
        return a>y.a;
    }
};

int main(){
    int n;
    cin>>n;
    map<k,bool> mp;
    priority_queue<k>que;
    for (int i=0;i<n;i++){
        int x,y;
        cin>>x>>y;
        que.push((k){x-y,x+y});
        mp[(k){x-y,x+y}]=1;
    }
    int ans=n+1;///n个圆至少分成n+1个面
    while (que.size()>=2){
        k k1=que.top();
        que.pop();
        k k2=que.top();
        if (k1.a==k2.a){///如果左端点相同,那么如果两个右端点形成的线段存在平面数++
            if (mp[(k){k1.b,k2.b}]) ans++;
            else que.push((k){k1.b,k2.b});///如果不存在,那么大的圆等效于一个从k1.b到k2.b的圆
        }
    }
    cout<<ans<<endl;
    system("Pause");
}

自己的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
using namespace std;
struct forma
{
    int left,right;
    friend bool operator < (forma a,forma b )
    {
        if(a.left!=b.left)
          return a.left>b.left;
        return a.right>b.right;
    }
};
int main()
{
    int num;
    scanf("%d",&num);
    map<forma,bool>mp;
    priority_queue<forma>q;
    int ans=num+1;
    int x,r;
    while(num--)
    {
        scanf("%d%d",&x,&r);
        mp[(forma){x-r,x+r}]=true;
        q.push((forma){x-r,x+r});
    }
    while(q.size()>=2){
        forma test1=q.top();
        q.pop();
        forma test2=q.top();
        if(test1.left==test2.left){
        if(mp[(forma){test1.right,test2.left}])
            ans++;
        else
            q.push((forma){test1.right,test2.left});
       }
    }
    printf("%d\n",ans);
    // system("Pause");
}

关于运算符的重载:


struct point{    
    int x;    
    int y;    
    int times;    
    friend bool operator < (point a, point b)    
    {    
        return a.times > b.times;    //重载小于号使得小的先出队列    
    }    
};  

在此处定义一个优先队列priority_queue<point> q;

如果要按照以times进行从小到大排列,操作如上。

进行重载<操作符。

意思是如果a.times > b.times成立,那么结构体point a < point b成立。由于优先队列是按照从大到小排列,所以结构体b会排列到a之前,然而b.times是最小的,所以实现了按照times的从小到大排序,其实用一句话说就是要想b更大那么b.times.

总结:重载小于号

若 >则为升序,<为降序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值