• 【2017西安】Sum of xor sum(线段树)


    Song Zha Zha has an 11-indexed array A . Li Zha Zha has QQ queries . Each query has two integers LL, RR , asking Ran Zha Zha to do the following thing .First , find all subintervals of [L,R][L,R] . Then calculate their xor sum . For example .

    A={1,2,3}A=1,2,3 , L=1L=1, R=3R=3.

    All subintervals of [1,3][1,3] are [1,1],[2,2],[3,3],[1,2],[2,3],[3,3][1,1],[2,2],[3,3],[1,2],[2,3],[3,3] .Their xor sum = 1 + 2 + 3 + 11+2+3+1 xor 2 + 22+2xor 3 + 13+1 xor 22 xor 33 .

    Xor means exclusive or . (^ in C++ or Java )

    Input

    The input contains multiple test cases.

    First line contains an integer T(1 le T le 10)(1T10) , which is the number of test cases .

    In each test case:

    The first line contains two integers NN, QQ. (1 le N,Q le 100000)(1N,Q100000) . NN is the length of the array AA .

    Then one line contains NN integer indicating A[i]A[i] . (1 le i le N , 0 le A[i] le 1000000)(1iN,0A[i]1000000).

    Then QQ lines follow . Each line two integer L,RL,R , means that there’s a query [L,R][L,R] . (1 le L le R le N)(1LRN).

    OutputFor each query, print the answer mod 10000000071000000007.

    样例输入

    1
    3 1
    1 2 3
    1 3

    样例输出

    10

    题目来源

    ACM-ICPC 2017 Asia Xi'an

    SOLUTION:

    FROM:https://www.cnblogs.com/RRRR-wys/p/9749591.html

     

    首先,我们考虑拆位,分别计算每一位的贡献然后合并出答案,现在序列的元素只包含0或1。我们希望用线段树维护,异或为1的区间的个数,即包含奇数个1的区间的个数。那么,假设现在已知,[L,mid]有多少个区间包含奇数个1,[mid+1,R]有多少个区间包含奇数个1,那么合并后的区间的答案,就是左边的答案+右边的答案+横跨两个区间的答案。

     

    横跨两个区间的答案 = (左边以mid为右端点包含奇数个1的区间的数目) * (右边以(mid+1)为左端点包含偶数个1的区间的数目) + (左边以mid为右端点包含偶数个1的区间的数目) * (右边以(mid+1)为左端点包含奇数个1的区间的数目)

     

    那么现在就需要我们维护上边这4个东西,显然如果知道奇数的贡献,就很容易可以计算出偶数贡献。所以实际只用维护2个东西。这两个东西也可以用类似的思想维护出来,所以我们不用维护其他的东西了。引用大佬的话:“这类题目就是需要什么维护什么,直到数据结构自洽”当然,如果发现需要维护的东西过多,就要考虑换个思路了。

     

     

    CODE:

    #include <bits/stdc++.h>
    #define pb push_back
    typedef long long ll;
    const int N = 1e5 + 7;
    const int inf = 0x3f3f3f3f3f;
    const int mod = 1e9 + 7;
    using namespace std;
    int T, n, q, a[N];
    struct node{
        ll ans[20], lx[20], rx[20];
        int num[20], len;
    } tree[N<<2];
    node mer(node &a,node &b) {
        node res;
        for(int i = 0; i < 20; ++i) {
            res.ans[i] = a.ans[i] + b.ans[i];
            res.ans[i] += a.lx[i]*(b.len - b.rx[i]);
            res.ans[i] += (a.len - a.lx[i])*b.rx[i];
            if(b.num[i] & 1) res.lx[i] = b.lx[i] + (a.len - a.lx[i]);
            else res.lx[i] = b.lx[i] + a.lx[i];
            if(a.num[i] & 1) res.rx[i] = a.rx[i] + (b.len - b.rx[i]);
            else res.rx[i] = a.rx[i] + b.rx[i];
            res.num[i] = a.num[i] + b.num[i];
        }
        res.len = a.len + b.len;
        return res;
    }
    void build(int p, int l, int r) {
        if(l == r) {
            tree[p].len = 1;
            for(int i = 0; i < 20; ++i)
                if( a[l] & (1<<i) ) tree[p].ans[i] = tree[p].lx[i] = tree[p].rx[i] = tree[p].num[i] = 1;
                else tree[p].ans[i] = tree[p].lx[i] = tree[p].rx[i] = tree[p].num[i] = 0;
            return;
        }
        int mid = (l + r) >> 1;
        build(p<<1, l, mid); build(p<<1|1, mid+1, r);
        tree[p] = mer(tree[p<<1],tree[p<<1|1]);
    }
    node ask(int p,int l,int r,int L,int R) {
        if(l == L && R == r) {
            return tree[p];
        }
        int mid = (l + r) >> 1;
        if(R <= mid) return ask(p<<1,l,mid,L,R);
        else if(L > mid) return ask(p<<1|1,mid+1,r,L,R);
        else {
            node tmp1 = ask(p<<1,l,mid,L,mid);
            node tmp2 = ask(p<<1|1,mid+1,r,mid+1,R);
            return mer(tmp1,tmp2);
        }
    }
    int main() {
        scanf("%d", &T);
        while( T-- ) {
            scanf("%d%d",&n,&q);
            for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
            build(1,1,n);
            while(q--) { int l, r;
                scanf("%d %d",&l,&r);
                node tmp = ask(1,1,n,l,r);
                ll ans = 0;
                for(int i = 19; i >= 0; --i) 
                    ans = ((ans<<1LL)%mod + tmp.ans[i])%mod;
                printf("%lld
    ",ans);
            }
        }
        return 0;
    }
    

      

     

     

     

     

  • 相关阅读:
    Java 实例
    为什么很多程序员工作时都戴耳机?
    HTTP状态码大全
    Eclipse怎么切换工作空间
    maven POM.xml内的标签大全详解
    利用html5的FormData对象实现多图上传
    后台定时器注解方式
    js多定时器
    解决ios上微信无法捕获返回键按钮事件的问题
    上传文件,获取表单数据和文件流
  • 原文地址:https://www.cnblogs.com/zhangbuang/p/11270054.html
Copyright © 2020-2023  润新知