c++进制转换+扫描线算法(二维区间合并面积和)

💬前言

💡本文展现个人常用进制转换写法以及扫描线扩展算法
💛 💙 💜 ❤️进制转换是非常常用且容易疏忽大意的部分,励志通过本文让大家掌握进制转换 💛 💙 💜 ❤️
如果对您有帮助的话还请动动小手 点赞👍收藏⭐️关注❤️

👑进制转换

🍋十进制转16进制

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

char change(int x)
{
	if(x < 10) return x + '0';  //【0-9】 
	return (char)('A' + x - 10); //【A-F】 
}

int main()
{
	int n;
	cin >> n;
	string s = ""; 
	while(n)
	{
		char x = change(n % 16);
		n /= 16;
		s = x + s; //【省reverse】 
	}
	cout << s << endl; 
	return 0; 
} 

🍋16进制转十进制

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

int get(char c)
{
	if(c - '0' < 9) return  c - '0';
	return c - 'A' + 10;
}

 int main() 
{
	//string读入 hex
	string s;
	cin >> s;
	res = 0; 
	for(int i = 0; i < s.size(); i++) //秦九韶
	{
		res = res * 16 + get(s[i]);
	}
	cout << res << endl;
	
	return 0; 
} 

🍋36进制转十进制 [0-9, A-Z] ---- 16改为36

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

int get(char c)
{
	if(c - '0' < 9) return  c - '0';
	return c - 'A' + 10;
}

 int main() 
{
	//string读入 hex
	string s;
	cin >> s;
	res = 0; 
	for(int i = 0; i < s.size(); i++) //秦九韶
	{
		res = res * 36 + get(s[i]);
	}
	cout << res << endl;
	
	return 0; 
} 

(被注释部分-舍弃)

	//int读入(没有A-F的hex) (娱乐hh)
//	int n;  //用秦九韶 - 从高位开始 - 先翻转n 
//	scanf("%d", &n);
//	string sn = to_string(n);
//	cout << sn << endl;
//	reverse(sn.begin(), sn.end());
//	
//	int ns = stoi(sn);	
//	cout << ns << endl;
//	LL res = 0;
//	while(ns)
//	{
//		res = res * 16 + ns % 10;
//		ns /= 10;
//	}
//	cout << res << endl;

💎扩展

🍅3068. 扫描线

在二维平面中给定 n 个两条边分别与 x 轴和 y 轴平行的矩形,请你求出它们的面积并。

输入格式
第一行包含整数 n。
接下来 n 行,每行包含四个整数 x1,y1,x2,y2,表示其中一个矩形的左下角坐标 (x1,y1) 和右上角坐标 (x2,y2)。
注意,坐标轴 x 轴从左向右延伸,y 轴从下向上延伸。

在这里插入图片描述

输出格式
一个整数,表示矩形的面积并。

数据范围
1≤n≤1000,
− 1 0 9 −10^9 109≤x1<x2≤ 1 0 9 10^9 109,
− 1 0 9 −10^9 109≤y1<y2≤ 1 0 9 10^9 109

输入样例:
2
10 10 20 20
15 15 25 25

输出样例:
175


二维坐标合并 O ( n 2 l o g n ) \large二维坐标合并O(n^2logn) 二维坐标合并O(n2logn)

①预处理划分区域坐标-枚举(矩形横坐标l[i].x,r[i].x)放入xs[类似离散化但不去重]sort 
[(xs[i]!=xs[i+1]时)枚举划分区域]
②range_area计算区域面积:先计算与区域有交集的矩形{l[i].y,r[i].y}存到q[cnt]-sort做区间合并:
区域面积=高度和res * 宽度(b-a)   
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
const int N = 1010;

int n;
PII l[N], r[N]; //左上角 和 右下角
PII q[N]; //存每个区域有交集的矩形高度

LL range_area(int a, int b) //每个垂直划分区域(宽度) - 左右坐标
{
    int cnt = 0;  //预处理 - 矩形 [左,右]>=[a, b] 数量
    for (int i = 0; i < n; i ++ )
        if (l[i].x <= a && r[i].x >= b) //矩形左右>=区域左右边界 - 有交集[矩形可被分割]
            q[cnt ++ ] = {l[i].y, r[i].y}; //存矩形高度
    if (!cnt) return 0;  //没有矩形有交集
    sort(q, q + cnt); //【区间合并-高度y】-同一区域有交集的矩形高度y做区间合并
    LL res = 0;
    int st = q[0].x, ed = q[0].y; //边界取第一个, 
    for (int i = 1; i < cnt; i ++ )  //从1开始(第二个边界开始)比较
        if (q[i].x <= ed) ed = max(ed, q[i].y);
        else
        {
            res += ed - st; //[累加高度]  
            st = q[i].x, ed = q[i].y;
        }
    res += ed - st; //[累加高度]
    return res * (b - a); //累加高 * 宽度
}

int main()
{
    scanf("%d", &n);
    vector<int> xs; //存所有横坐标x
    for (int i = 0; i < n; i ++ )
    {
        scanf("%d%d%d%d", &l[i].x, &l[i].y, &r[i].x, &r[i].y);
        xs.push_back(l[i].x), xs.push_back(r[i].x);  //存所有点的横坐标x     
    }
    sort(xs.begin(), xs.end()); //横坐标排序-(枚举区间宽度) - 无需判重
    LL res = 0; //LL
    for (int i = 0; i + 1 < xs.size(); i ++ ) //i+1 < 边界xs.size()
        if (xs[i] != xs[i + 1]) //枚举宽度 - (重复坐标就不判断)
            res += range_area(xs[i], xs[i + 1]); //加上面积
    printf("%lld\n", res);
    return 0;
}

扫描线原理图-划分:
在这里插入图片描述

区间合并版

LL range_area(int a, int b)
{
    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        if(l[i].x <= a && r[i].x >= b) 
            q[cnt ++] = {l[i].y, r[i].y};
    }
    if(cnt == 0) return 0;
    sort(q, q + cnt);
    LL res = 0;
    int st = -2e9, ed = -2e9; //边界
    for(int i = 0; i < cnt; i++)   
    {
        if(ed < q[i].x) 
        {
            if(st != -2e9)res += ed - st; //非边界(特判第一个)
            st = q[i].x, ed = q[i].y;
        }
        else ed = max(ed, q[i].y);
    }
    if(st != -2e9)res += ed - st;  //别忘加最后一个(若没有合并区间,则cnt已经return,可不加if判断)
    return res * (b - a);
}
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

violet~evergarden

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值