• 洛谷3794:签到题IV——题解


    https://www.luogu.org/problemnew/show/P3794

    题目见上。

    有一个套路(虽然我到现在还不会),就是固定一个端点,二分查右端点。

    显然这题的正解是O(nlogn)的,那么这个套路没准好用。

    考虑固定了左端点,因为每次区间gcd都要比上一个区间gcd/2或不变,能够证明一共有O(log)种取值。

    而或同理,每次在一个进制位上+1,同样有O(log)种取值。

    因此我们二分求出每块gcd值相等的块,然后再求出每块或值相等的块,按照题目要求取个或就行了,可以st表维护,为O(nlog^2)的复杂度。

    这个多出来的log是因为我们对于log gcd块内每次log或块,自然变慢,考虑能不能后来的块继承前面的块的信息。

    当然可以,于是你就有了下面的正解(代码很好读我就不写解释了),到这篇博客写完为止,开O2 rk1.

    #include<cmath>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct range{
        int l,r,v;
    }g[N],o[N];
    int n,k,a[N],mp[4*N];
    inline int gcd(int a,int b){
        return b?gcd(b,a%b):a;
    }
    inline void merge(range t[],int &l){
        int len=0;
        for(int i=1;i<=l;i++){
        if(!len||t[len].v!=t[i].v)t[++len]=t[i];
        else t[len].l=t[i].l;
        }
        l=len;
    }
    int main(){
        n=read(),k=read();
        for(int i=1;i<=n;i++)a[i]=read();
        ll sum=0;int r1=0,r2=0;
        for(int i=n;i>=1;i--){
        for(int j=1;j<=r1;j++)g[j].v=gcd(g[j].v,a[i]);
        for(int j=1;j<=r2;j++)o[j].v=o[j].v|a[i];
        g[++r1]=(range){i,i,a[i]};o[++r2]=(range){i,i,a[i]};
        merge(g,r1);merge(o,r2);
        for(int j=1;j<=r2;j++)mp[o[j].v]=j;
        for(int j=1;j<=r1;j++){
            int p=mp[g[j].v^k];
            if(!p)continue;
            int l=g[j].l,r=g[j].r;
            l=max(l,o[p].l),r=min(r,o[p].r);
            if(l<=r)sum+=r-l+1;
        }
        for(int j=1;j<=r2;j++)mp[o[j].v]=0;
        }
        printf("%lld
    ",sum);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    Spring框架 基础01
    Mybatis框架 基础
    字节流,字符流
    集合的应用(练习:学生档案)
    集合
    时间类型的格式化(字符串和时间类型 之间的相互转换)
    逢三退一(boolean数组的使用)
    电子宠物(线程,实现方法)
    点是否在圆里
    sqlserver 指定上月25-本单据日期/本月24 数据汇总的保存后存储过程
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9095773.html
Copyright © 2020-2023  润新知