UVALive 8518 - Sum of xor sum

UVALive 8518 - Sum of xor sum


做法:线段树维护:答案,边界在左端点的区间异或为1的个数,边界在右端点异或为1的个数,1的个数,区间长度,这样已经自洽了。(每次讲线段树,都会讲这个题,比较经典的思想)

#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\n",ans);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/RRRR-wys/p/9749591.html
sum