四校联考(20170910)
ditoly出的题目果然丧,待我一天啃一题。。。。。
废话不多说,开更:
————————————————————我是分割线——————————————————
T1:最大值(max)
【问题描述】
小C有n个区间,其中第i个区间为[li,ri],小C想从每个区间中各选出一个整数,使得所有选出的数and起来得到的结果最大,请你求出这个值。
【输入格式】
第一行一个正整数n,表示区间个数。
接下来n行,每行两个非负整数li,ri。
【输出格式】
输出一个整数,表示答案。
【样例输入】
2
1 3
4 6
【样例输出】
2
【数据范围】
对于数据点1~2,sum(ri-li+1)(1<=i<=n)不超过10^7;
对于数据点3~4,存在一个x满足对于每个区间,li<=x<=ri;
对于数据点5~6,n=2;
对于数据点7~8,ri<=10^5;
对于全部数据(1~10),n<=10^5,li<=ri<=10^18。
————————————————————我是分割线——————————————————
神奇题目emmmmm
我们先要明白一个事情,那就是假如说我们从大到小枚举i,如果所有的区间在二进制下第i位都可以取到1,那么显然这个1一定作为答案
那么我们怎么处理接下来的区间呢?
我们分情况讨论,假如说所有的区间在目前的第i位都可以取到i,那么枚举每一个区间,假如目前区间的左端点不能取到1,那么我们就把li赋值为0,因为我们的判断是靠ri判断的,不影响答案。表示我们后面的数都可以取到0,而这样做可以证明不会使答案变得更劣。
那么如果不能满足所有的区间都取到1,那么我们继续分情况讨论:
如果所有的区间这一位都只能取到0,那么就取0
否则如果有的区间可以取0,有的区间可以取1,那么我们显然取0,因为取1&之后还是0,而取0之后1~i-1位都可以取1,一定最优。所以我们把满足这种条件的区间的右端点设为(1<<i)-1
然后就是贴代码啦!
#include<cstdio> #define MN 100005 long long l[MN],r[MN],ans; int main() { freopen("max.in","r",stdin); freopen("max.out","w",stdout); int n,i,j; scanf("%d",&n); for(i=1;i<=n;++i)scanf("%I64d%I64d",&l[i],&r[i]); for(i=60;i--;) { for(j=1;j<=n;++j)if(!(r[j]&(1LL<<i)))break; if(j>n)for(ans+=1LL<<i,j=1;j<=n;++j){if(!(l[j]&(1LL<<i)))l[j]=0;} else for(j=1;j<=n;++j)if((l[j]&(1LL<<i))!=(r[j]&(1LL<<i)))r[j]=(1LL<<60)-1; } printf("%lld\n",ans); fclose(stdin); fclose(stdout); }
————————————————————我是分割线——————————————————