• codeforce gym 100307H Hack Protection


    原题地址:http://codeforces.com/gym/100307/problem/H

    题意:

    给定一个序列,求序列的子区间中,满足子区间XOR值等于AND值得子区间个数。

    题解:

    一直以为NEERC这种有名的比赛应该题解到处都是,太天真了……

    首先考虑区间的AND值。

    对于固定起点的区间,因为 & 的性质,AND值必然单调递减,并且,根据AND值中1的个数划分后面的区间,必然最多只能划分成32段,对于某一段中的任意位置,它和固定的起点所形成的子区间的AND值是一样的。

    再来考虑区间的XOR值

    对于数列A[],定义sum(a,b)=A[a]^A[a+1]^...^A[b];

    那么sum(a,b)=(A[1]^A[2]^...^A[a-1])^((A[1]^A[2]^...^A[a-1])^(A[a]^A[a+1]^...^A[b])=sum(1,a-1)^sum(1,b),这是一个前缀和形式

    考虑题给的等式,AND(a,b)==XOR(a,b)

    也就是AND(a,b)==XOR(1,a-1)^XOR(1,b)

    也就是AND(a,b)^XOR(1,a-1)==XOR(1,b) ——(1)

    我们枚举区间的起点,XOR(1,a-1)是定值,接下来枚举AND值相同的区段,最多32段,在每一段中寻找满足等式(1)的b,累计答案

    区间AND值可以用RMQ思想处理,区段的划分可以二分处理,而寻找区段中XOR值为固定值的元素个数,可以转化为前缀和

    #include<bits/stdc++.h>
    
    #define clr(x,y) memset((x),(y),sizeof(x))
    
    using namespace std;
    typedef long long LL;
    
    struct seg
    {
        int l;
        int val;
    };
    
    const int maxn=1e5;
    
    int AND[maxn+5][18];
    int XOR[maxn+5];
    int n;
    int A[maxn+5];
    vector <seg> v[maxn+5]; //段划分
    map <int,vector<int> > mp; //mp[x]中储存XOR[1,a]==x的元素下标a
    
    void build() //计算区间AND值
    {
        for (int i=1;i<=n;++i)
            AND[i][0]=A[i];
    
        for (int j=1;(1<<j)<=n;++j)
        {
            for (int i=0;i+(1<<j)-1<=n;++i)
            {
                AND[i][j]=AND[i][j-1] & AND[i+(1<<(j-1))][j-1];
            }
        }
    }
    
    int calu(int l,int r)
    {
        int k=0;
        while ((1<<(k+1))<=r-l+1) ++k;
        return AND[l][k] & AND[r-(1<<k)+1][k];
    }
    
    LL Count(int l,int r,int val) //区间[l,r]中XOR值为val的元素个数
    {
        return upper_bound(mp[val].begin(),mp[val].end(),r)-lower_bound(mp[val].begin(),mp[val].end(),l);
    }
    
    void solve()
    {
        ++n;
        A[n]=0;//为了便于划分在末尾加上一个0
    
        build();
        for (int i=1;i<=n;++i) v[i].clear();
    
        for (int i=1;i<=n;++i)
        {
            int val=A[i];
            int l=i;
            int r=n;
    
            v[i].push_back((seg){l,val});
            while (val!=0) //不断二分划分段
            {
                int lb=l;
                int ub=r;
                while (ub-lb>1)
                {
                    int mid=(ub+lb)>>1;
                    if (calu(i,mid)==val)
                    {
                        lb=mid;
                    }
                    else
                    {
                        ub=mid;
                    }
                }
                l=ub;
                val=calu(i,l);
    
                v[i].push_back((seg){l,val});
            }
        }
    
        mp.clear();
        XOR[0]=0;
        for (int i=1;i<=n;++i)
        {
            XOR[i]=XOR[i-1]^A[i];
            mp[XOR[i]].push_back(i);
        }
    
        LL ans=0;
        for (int i=1;i<=n;++i)
        {
            for (int j=0;j<v[i].size();++j)
            {
                int l=v[i][j].l;
                int r=(j==v[i].size()-1)? n:v[i][j+1].l-1;
                int val=v[i][j].val^XOR[i-1];
    
                ans+=Count(l,r,val);
                //printf("%d %d %d
    ",l,r,val);
            }
        }
    
        //消除最后那个虚拟的0对答案的影响
        LL extra=1;
        int xor_tmp=0;
        for (int i=n-1;i>=1;--i)
        {
            xor_tmp^=A[i];
            if (xor_tmp==0) ++extra;
        }
        printf("%lld
    ",ans-extra);
    }
    
    int main(void)
    {
        #ifdef ex
        freopen ("../in.txt","r",stdin);
        //freopen ("../out.txt","w",stdout);
        #endif
    
        freopen("hack.in","r",stdin);
        freopen("hack.out","w",stdout);
    
        while (scanf("%d",&n)==1)
        {
            for (int i=1;i<=n;++i)
            {
                scanf("%d",&A[i]);
            }
            solve();
        }
    }
  • 相关阅读:
    深入剖析.NET运行机制
    在浏览器地址中加参数
    mysql 中文乱码
    今天在看一些面试题的时候遇到的一个关于strcmp()返回值的细节问题
    如何在学习过程中统一IDE的编码!
    通过文件方式,在文件内容开头写入字符串!
    Java编写圆的相关计算
    leetcode 上的Counting Bits 总结
    cocos2dx打包apk
    CEGUI0.8.4例子
  • 原文地址:https://www.cnblogs.com/123-123/p/5839317.html
Copyright © 2020-2023  润新知