Codeforces 1304C Air Conditioner 题解

题意简述

你有一个空调(承太郎),初始温度为$m$,有$n$个客人。第$i$个客人会在$t_i$的时间过来,适应的温度在$[l_i,r_i]$之间。每一个时刻,空调珂以让气温升高$1$(制热),减少$1$(制冷),或者不变(关掉空调)。

请问你能否满足所有顾客的适应温度?输出$YES/NO$。

$n<=1e6$,其余输入数据的绝对值都$<=1e9$。 (原来是$n<=100$,但是$n<=1e6$也能做)

思路框架

首先,将所有的顾客按$t_i$排序(显然)。

定义两个数$l,r$。初始$l=r=m$。

然后对于每个顾客,$[l,r]$两端都向外扩展$t_i-t_{i-1}$个长度($l$减去这个数,$r$加上这个数)。然后和$[l_i,r_i]$取一下交集。看看最后$[l,r]$是否非空,如果非空,输出$YES$,否则$NO$。

具体思路

如何得到这个算法的

(排序肯定是第一个想到的)

一开始我还以为这个是贪心之类的,然后我就在想,从第$i-1$个人到第$i$个人,到底该停留在哪个决策点呢?

后来我就从能得到的区间开始考虑:初始温度为$x$,经过$t$时刻,能得到的区间是$[x-t,x+t]$。

然后我就有了一个灵感:我们不用具体决策到哪一个点,我们只需要知道能到哪一个区间就珂以了!

于是就有了下面这个算法。

算法的解释&正确性

$[l,r]$表示当前空调在满足所有顾客需求的情况下能调整到的温度范围。初始值为$[m,m]$是显然的(第$0$时刻,空调还没开)

然后从第$i-1$个人到第$i$个人,经过了$t_i-t_{i-1}$个时刻。最小的情况显然是全开制冷,最大的情况显然是全开制热。而且,容易证明,在这段区间中所有的温度都能得到。当然,我们还要考虑上新进来的第$i$个顾客,所以扩展完这个区间还要和$[l_i,r_i]$取一下交集。

然后到最后看看这个范围是否非空即珂。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 155555
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),__v=G.To(i);~i;i=G.Next(i),__v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define iter(a,p) (a.begin()+p)
void R1(int &x)
{
x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=(f==1)?x:-x;
}
void Rd(int cnt,...)
{
va_list args;
va_start(args,cnt);
F(i,1,cnt)
{
int* x=va_arg(args,int*);R1(*x);
}
va_end(args);
}
struct node{int t,l,r;} a[N]; bool operator<(node a,node b){return a.t<b.t;}
int n,m;
void Input()
{
Rd(2,&n,&m);
F(i,1,n) Rd(3,&a[i].t,&a[i].l,&a[i].r);
sort(a+1,a+n+1);
}

void Soviet()
{
int l=m,r=m;
F(i,1,n)
{
l-=(a[i].t-a[i-1].t);
r+=(a[i].t-a[i-1].t);
l=max(l,a[i].l);
r=min(r,a[i].r);
if (l>r) {puts("NO");return;}
}
puts("YES");
}

#define Flan void
Flan IsMyWife()
{
int t;R1(t);
F(i,1,t)
{
Input();
Soviet();
}
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}
w