首页 > 其他分享 >【题解】洛谷P1496 火烧赤壁 (离散化)

【题解】洛谷P1496 火烧赤壁 (离散化)

时间:2023-12-24 14:34:09浏览次数:27  
标签:map 洛谷 P1496 int 题解 离散 区间 include

P1496 火烧赤壁 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我们首先先看数据,n<=20000,数据不多,但是范围大(-10^9<=Ai,Bi<=10^9),这时,就可以用离散化了。但是在这里我们会遇到区间重合的问题(也可以使用区间合并),如下图

本题的题意是让我们求出燃烧位置的长度之和。区间重合时只需要区间最大数减去最小数字,那么我们如何获得这个数字呢?

朴素的想法是,在面对一段连续的区间时,从边界一直枚举下去到尽头用if语句终止。当我们离散化后,也不会有数组长度的问题了。对于连续区间,我们会考虑差分和前缀和。但是,如果如何区分左边界和右边界呢?

我的想法是,我们只需要[l+1,r]之间的区间进行操作,这样求前缀和后,sum[l]就是0,其他都大于0。

直接看代码吧qwq

/* P1496 火烧赤壁
 * 作者: Yukie
 * 日期: 2023-12-24
 * 算法: 离散化(map方法)
 */

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int maxn = 2e4 + 5;
vector<PII> fire;
map<int, int> h;
int n, Map[2 * maxn], sum[2 * maxn];
LL ans;

int find(int value) {
	for (map<int, int>::iterator it = h.begin(); it != h.end(); it++) { 
		if (it->second == value)
			return it->first;
	}
} //由离散化后的结果找原来的数,因为key本身就唯一,映射后也是从1升序,所以key和value均唯一

int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int l, r;
		cin >> l >> r;
		fire.push_back({l, r});
		h[l] = 1, h[r] = 1;
	}

	//h[x]就是离散化后的结果,已排好序
	int idx = 1;
	for (auto &t : h) { // 使用auto修改map值时,需要添加引用符号&
		t.second = idx;
		idx++;
	}

	for (auto fi : fire) {
		int x = h[fi.first], y = h[fi.second];
		Map[x + 1]++, Map[y + 1]--; //差分,为什么是左边界+1呢?为了到时候查找时能区分出来左右,实际上问题转为[l+1,r]
	}

	for (int i = 1; i <= h.size(); i++)
		sum[i] += sum[i - 1] + Map[i]; //前缀和

	int l, r; //不为0的区间的左端点和右端点。

	for (int i = 1; i <= h.size(); i++) {
		if (sum[i] != 0 && sum[i - 1] == 0)  //查找连续着火区间的左边界
			l = i - 1;
		if (sum[i] != 0 && sum[i + 1] == 0) {
			r = i;  //查找连续着火区间的右边界
			ans += find(r) - find(l);
			//由于这是离散化后的区间长度,并不是真正的区间长度,所以我们要找到原来的l与r,将他们相减,就是原来的区间长度。
		}
	}
	cout << ans << endl;
	return 0;
}

 

样例解释:

输入区间排序后:-1 1 2 5 9 11

映射后:1 2 3 4 5 6

差分数组:0 1 -1 1 1 -1

前缀和数组:0 1 0 1 2 1

 

不用map的离散化版本:

(待补)

标签:map,洛谷,P1496,int,题解,离散,区间,include
From: https://www.cnblogs.com/Yukie/p/17924367.html

相关文章

  • [ABC265F] Manhattan Cafe 题解
    [ABC265F]ManhattanCafe题解思路解析很有思维难度的一道题。思路是dp,\(f[i][j][k]\)表示已经计算了\(i\)维,距离点\(p\)的距离为\(j\),距离点\(q\)的距离为\(k\)时的整点\(r\)个数,由此可见我们的每一维都可以从上一维推出来,也即\(f[i][j][k]\)可以由\(f[i-1][j......
  • ABC334 全套题解
    A-ChristmasPresent简单题。voidslv(){ inta=Read<int>(),b=Read<int>(); if(a>b)Puts("Bat"); elsePuts("Glove"); return;}B-ChristmasTrees也是简单题。constexpri128INF=-1e18;i128a,m,l,r;voidslv(......
  • 题解 ABC334G【Christmas Color Grid 2】
    先求出初始时绿连通块数量。将一个绿色格子染成红色,会改变绿连通块数量,当且仅当这个绿色格子是孤点或割点。如果是孤点,会使得绿连通块数量减少一;如果是割点,会使得绿连通块数量增加它所在的点双数量减一。根据上述规则可以求出每个绿色格子染红后的绿连通块数量,求平均值即可。时......
  • 题解 ABC334F【Christmas Present 2】
    设\(f_i\)表示假设只有编号为\(1\simi\)的点,此时的答案。\(f_n\)即为所求。显然有:\[f_i=\min\limits_{i-k\lej<i}\{f_j+dis(s\toj+1\toj+2\to\cdots\toi)\}+dis(i\tos)\]当\(i\toi+1\)时,大括号内部全局增加\(dis(i\toi+1)\),可以全局打标记后单调队列维护。......
  • 题解 ABC334E【Christmas Color Grid 1】
    先求出初始时绿连通块数量。枚举每个红色格子,将其染成绿色本应增加一个绿连通块,但是它每与一个绿连通块相邻,就又会减少一个绿连通块。根据上述规则可以求出每个红色格子染绿后的绿连通块数量,求平均值即可。时间复杂度\(O(nm)\)。//Problem:E-ChristmasColorGrid1//Co......
  • 检查Windows更新问题解决
    在任务栏搜索框输入cmd,点击右侧的“以管理员身份运行”,打开后输入:(建议复制粘贴,防止输入有误出现错误提示等请忽略*)SCconfigwuauservstart=auto回车(Enter按键)SCconfigbitsstart=auto回车(Enter按键)SCconfigcryptsvcstart=auto回车(Enter按键)SCconfigtrustedin......
  • 【题解】洛谷P1068 [NOIP2009 普及组] 分数线划定 (map)
    ##题目描述世博会志愿者的选拔工作正在A市如火如荼的进行。为了选拔最合适的人才,A市对所有报名的选手进行了笔试,笔试分数达到面试分数线的选手方可进入面试。面试分数线根据计划录取人数的$150\%$划定,即如果计划录取$m$名志愿者,则面试分数线为排名第$m\times150\%$(向......
  • P3893 [GDOI2014] Beyond 题解
    P3893[GDOI2014]Beyond题解思路称第一个字符串为\(A\),第二个字符串\(B\)。考虑枚举环长\(L\),那么如果\(L\)是可行的,当且仅当存在一个位置\(i\),使得\(A_{1\simi}=B_{L-i+1,L},A_{i+1\simL}=B_{1,L-i}\),也就是\(A_{1\simL}\)的一个前缀和\(B_{1\s......
  • 洛谷 P1229
    题目链接有4种结构。对于只有一个儿子(度为1)的结点,其子节点在左/右不影响先序/后序的遍历顺序,总树数*2。即每多一个度为1的结点,二叉树数量翻倍。即当先根序列为\(.....XY.....,\)后根序列为\(.........YX...\)时翻倍。求出这种结构的个数即可。#include<bits/stdc++.h>usi......
  • 【洛谷 P1781】宇宙总统 题解(高精度+结构体排序)
    宇宙总统题目描述地球历公元6036年,全宇宙准备竞选一个最贤能的人当总统,共有个非凡拔尖的人竞选总统,现在票数已经统计完毕,请你算出谁能够当上总统。输入格式第一行为一个整数,代表竞选总统的人数。接下来有行,分别为第一个候选人到第个候选人的票数。输出格式共两行,第一行是......