四校联考(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~6n=2

对于数据点7~8ri<=10^5

对于全部数据(1~10),n<=10^5li<=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);
}

 

————————————————————我是分割线——————————————————

 

posted @ 2017-09-11 17:26  ghostfly233  阅读(164)  评论(0编辑  收藏  举报