题外话
这道题……
一道黄题。
一道简单的思维题。
题意简述
有一个量,初始为m,每单位时间可将其+1或-1或不变。现有n个三元组(t,l,r),要求且仅要求在t时刻该量的值需要在区间[l,r]内,问是否能满足这n个三元组的要求。
算法概述
数据中n个三元组都是按t的顺序给出的,所以无需我们自行排序。
首先考虑第一个三元组如何满足,可以启发我们如何去判断后面的三元组。
初始为0时刻值为m,第一个要求是t时刻在[l,r]内,我们可以考虑从0到t这段时间内,我们所能变化到的值域区间是[m-t,m+t],那么只需考虑[l,r]与[m-t,m+t]是否有交即可,然后这一时刻的取值范围即为这个交集区间。
然后考虑推广。在第i个三元组时,即ti时刻,当前的取值范围假设为[L,R],第i+1个三元组的要求是在ti+1时刻,需要在区间[li+1,ri+1]内,那么我们设d=ti+1-ti,则我们所能变化到的值域区间即为[L-d,R+d],那么ti+1时刻的取值范围即为[L-d,R+d]与[li+1,ri+1]的交集。
如此,我们便得到了一个很好的可以解决该问题的算法:
初始的取值范围为[m,m],然后依次遍历n个三元组,对于每个三元组,根据t计算出与上一个三元组的时间差d,然后通过上一个取值范围[L,R]计算出当前所能达到的值域区间[L-d,R+d],然后将这个值域区间与当前三元组的要求范围[l,r]取交集即为新的取值范围。
无解的情况则只需看在过程中,每次取交集时,取出的交集区间是否合法即可。也就是说,每次需要取交集时,若出现没有交集的情况,即为无解。
至于区间求交的方法,假设有两个区间[l1,r1],[l2,r2],两者的交集即为[max(l1,l2),min(r1,r2)],合法条件是max(l1,l2)<=min(r1,r2)。
参考代码
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N=110; int l[N],r[N],t[N]; int T,n,t0; void get_inter(int l1,int r1,int l2,int r2,int &ans_l,int &ans_r) { ans_l=max(l1,l2); ans_r=min(r1,r2); } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&t0); int L=t0,R=t0,flag=1; for(int i=1;i<=n;i++) scanf("%d%d%d",&t[i],&l[i],&r[i]); for(int i=1;i<=n;i++) { int dlt=t[i]-t[i-1]; int l1=L-dlt,r1=R+dlt; get_inter(l1,r1,l[i],r[i],L,R); if(L>R) { flag=0; break; } } if(flag)printf("YES "); else printf("NO "); } return 0; }