普通DP——CF1547EAir Conditioners

CF1547E——Air Conditioners

题目传送门: Priority Queue

这道题很显然一个格子会受到多个空调的影响,空调本身有一个温度,这个格子离空调越远温度越高,然后这个格子的温度为多个空调中最小值。

很显然我们不需要把每个空调对每个格子算出来,数据范围不允许我们这么暴力。我们仔细思考,格子和格子之间显然存在一个转化关系。

首先一个格子如果能够求出来,那么我们可以用O(1)的复杂度算出旁边的格子, 这里我们主要思考的是这个格子到底是被哪个空调所影响:

我们先用优先队列来维护对第一个格子的温度(升序),第一个格子显然得到答案,但是其他格子怎么考虑呢:

  • 假如两个格子都在所有空调的左边,那么这个两个格子,那么绝对是优先队列的第一个。
  • 假如这个格子在优先队列的第一个和第二个之间我们可以通过计算来得到是哪个
  • 如果第二个空调的温度始终比第一个高(第二个空调的温度 > 第一个空调的温度 + 两者的距离的差值),那么我们就可以用第一个空调和第三个空调比较,以此类推
  • 如果第一个空调没有第二个空调凉快,那么我们就用第二个空调和第三个空调比较

记住这里的关键是影响一个格子的空调数量最多两个。我们只要算这两个空调的温度即可。

感觉挺简单的感觉唯一学到的东西是那个结构体的\(cmp\)似乎是反着来的。

#include<iostream>
#include<string>
#include<queue>
#include<cmath>
using namespace std;
const int maxn = 3e5+10;
int ans[maxn];
int airpos[maxn];
int airtemp[maxn];
struct Node{
	int temp, pos;
	int temp2;
};

struct cmp{
	bool operator () (const Node & a, const Node & b) const 
	{
		return a.temp2 > b.temp2;
	}
};

priority_queue<Node, vector<Node>, cmp> q;

int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		int n, m;
		Node now;
		scanf("%d %d", &n, &m);	
		for(int i = 1; i <= m; i++)
			scanf("%d", &airpos[i]);
		for(int i = 1; i <= m; i++)
			scanf("%d", &airtemp[i]);
		for(int i = 1; i <= m; i++)
		{
			now.pos = airpos[i];
			now.temp = airtemp[i];
			now.temp2 = now.temp + abs(now.pos -1);
			q.push(now);
		}

		int cnt = 1;
		Node air1, air2;
		air1 = q.top();
		q.pop();
		
		while(cnt <= air1.pos)
		{
			ans[cnt] = air1.temp + abs(air1.pos - cnt);
			cnt++;
		}
		while(q.size())
		{
			air2 = q.top();
			q.pop();
			if(air2.pos < air1.pos) continue;
			
			while(cnt <= air1.pos)
			{
				ans[cnt] = air1.temp + abs(air1.pos - cnt);
				cnt++;
			}
			
			if(air2.pos-air1.pos+air1.temp < air2.temp) continue;
//			printf("HHHH");
			while(air1.temp + abs(cnt - air1.pos) < air2.temp + abs(air2.pos - cnt))
			{
//				printf("GGG");
				ans[cnt] = air1.temp+abs(cnt-air1.pos);
				cnt++;
			}
			air1 = air2;
		}
		
		for(int i = cnt; i <= n; i++)
		{
			ans[i] = air1.temp + abs(i - air1.pos);
		}
		for(int i = 1; i <= n; i++)
			printf("%d ", ans[i]);
		printf("\n");			
	}	
	
	
	
	return 0;
} 
posted @ 2021-07-13 15:34  斌斌翻水水  阅读(83)  评论(0)    收藏  举报