五一有幸跟着老师去了一次杭电,求虐之行,坐等清华北大等巨巨AK全场,总结经验,激励前进!
【题目链接】click here~~
【题目大意】在多个不确定区间里面,问能否选出三个互不相交的区间
【解题思路】
ps:当时是hjs敲题,敲完之后三个人都检查了一遍,发现没有问题,但是交上去却CE了,后面于是各种调,各种错误,最后发现把取模去掉,直接判断一下是否存在一个区间位于已经出来的区间中间且不交叉即可,悲剧。。。
【官方解题报告】首先我们考虑如何选择最左边的一个区间,假设最左边的区间标号是i, 那选择的另外两个区间的左端点必定要大于Ri,若存在i之外的j, 满足Rj<Ri, 那么另外两个区间的选择余地必定不会减少,因此,为了使另外两个区间有尽可能多的选择,我们选择一个右端点最小的区间作为最左边的区间是最好的,同理,我们选择一个左端点最大的区间为最右边的区间,也将提供最多的选择,确定了这两个区间之后,只需判断是否存在一个区间位于它们中间且不交叉即可
本题的取模值十分特殊,用unsigned int的自然溢出可以达到同样的效果,时间复杂度O(N)
代码:
#include <bits/stdc++.h> using namespace std; const int N=1e7+10; const int inf=0x3f3f3f3f; struct node { unsigned int pre,last; } Map[N]; int main() { int T,n; unsigned int L1,R1,a,b,c,d,maxx,minn; bool flag; scanf("%d",&T); while(T--) { flag=false; cin>>n>>L1>>R1>>a>>b>>c>>d; maxx=0; minn=inf; Map[0].pre=L1; Map[0].last=R1; for(int i=1; i<n; i++) { Map[i].pre=Map[i-1].pre*a+b; Map[i].last=Map[i-1].last*c+d; } for(int i=0; i<n; i++) { if(Map[i].pre>Map[i].last) swap(Map[i].pre,Map[i].last);//全部处理之后再交换! if(Map[i].pre>maxx) maxx=Map[i].pre;//左端点最大的区间作为最右边的区间 if(Map[i].last<minn) minn=Map[i].last;//右端点最小的区间作为最左边的区间 } for(int i=0; i<n; i++) { if(Map[i].last<maxx&&Map[i].pre>minn) { puts("YES"); flag=true; break; } } if(!flag) puts("NO"); } return 0; }