题解 | #骰子魔术#

E题

看了官方讲解视频的思路后才写出来

1.设f[l,r]==(a l ​ & a l+1 ​ &...& a r ​ )⊕(a l ​ ∣ a l+1 ​ ∣...∣ a r ​)

2.根据f[l,r]表达式,仅观察[l,r]中二进制数第k位的情况下,同时出现1和0才能使f[l,r]的第k位是1

3.那么符合题意的区间f[l,r]的二进制数最高位1的位数必须在[k1,k2-1]中

4.用双指针或者二分预处理出数组l[k][i]:在第k位下,从第i个数第l[k][i]个数第一次同时出现0和1,即第一次出现f[l,r]在第k位下等于1

#include<bits/stdc++.h>
#define int long long
using namespace std;

int n,k1,k2,a[500005],l[65][500005];

signed main()
{
    cin>>n>>k1>>k2;
    for(int i=1;i<=n;i++)cin>>a[i];
    
    if(k1>=60)
    {
        cout<<0;
        return 0;
    }
    
    int len=60;//1e18的二进制数长为60
    for(int k=0;k<len;k++)//枚举位数,然后用双指针算法处理出数组l[][]
    {
        int cnt0=0,cnt1=0;//0的个数,1的个数
        for(int i=1,j=1;j<=n;j++)
        {
            int t=((a[j]>>k)&1);
            t?cnt1++:cnt0++;
            while(cnt0 && cnt1)//同时存在0和1
            {
                l[k][i]=j;
                int t=((a[i++]>>k)&1);
                t?cnt1--:cnt0--;
            }
        }
    }
    
    //符合条件的区间:f[l,r]的二进制数最高1的位数在[k1,k2-1]
    int ans=0;
    for(int i=1;i<=n;i++)//枚举左边界
    {
        int a=n+1,b=n+1;
        for(int k=k1;k<len;k++)
        {
            if(l[k][i]==0)continue;
            if(k<=k2-1)a=min(a,l[k][i]);
            else b=min(b,l[k][i]);
        }
        if(a==n+1)continue;
        ans+=max(b-a,0LL);
    }
    cout<<ans;
    
    return 0;
}
全部评论

相关推荐

渐好:软光栅真的写明白了吗,既然是软渲那技术栈不应该使用OpenGL,光追和bvh既不算什么高级渲染技术更不应该属于软渲的内容,git那个项目没啥用,建议把前两个项目重新组织一下语言,比如软渲染那个项目 冯着色和msaa、贴图这几项分开写,写的到位点,如果你还学过光追那就单独写出来,如果没把握考官问你答不上来就别写给自己找麻烦,在技术栈那一栏简单提一下自己学过就行,这样杂的放在一起不太严谨,个人愚见.
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务