I am trying to solve Xor sum problem from Hackerearth Practice.
I am not getting the idea on how to apply the merge operation in the construction of segment tree for this problem. Any hints with code is appreciated.
Thank you ![]()
I am trying to solve Xor sum problem from Hackerearth Practice.
I am not getting the idea on how to apply the merge operation in the construction of segment tree for this problem. Any hints with code is appreciated.
Thank you ![]()
You need the count of each bit, Let a_i denote the number of times bit i is set, and b_i denote the number of times it is not set in the given range. The answer is \sum (\binom{a_i}{1}\binom{b_i}{2} + \binom{a_i}{3}\binom{b_i}{0} )\times 2^i
I got it, so for a triple xor to be 1 you need to have 1 set bit and 2 non-set bits or 3 set bits. Number of ways of doing that is what given right?
Thank you
)
I guess segment tree is used to get those number of set and non-set bits in a range.
Implemeting it using fenwick tree would be quite easier
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define MOD 1000000007
ll n,q,a[100005],seg[400005][45],l,r,po[100005];
/*void build(ll node,ll st,ll en)
{
if(st==en)
{
for(ll i=0;i<=42;i++)
{
if(a[st]&(1<<i))
seg[node][i]=1;
}
}
else
{
ll mid=(st+en)/2;
build(2*node,st,mid);
build(2*node+1,mid+1,en);
for(ll i=0;i<=42;i++)
{
seg[node][i]=seg[2*node]+seg[2*node+1];
}
}
}
ll qry(ll node,ll st,ll en,ll l,ll r,ll idx)
{
if(st>en||st>r||en<l||l>r)
return 0;
else if(st>=l&&en<=r)
return seg[node][idx];
else
{
ll mid=(st+en)/2;
return qry(2*node,st,mid,l,r,idx)+qry(2*node+1,mid+1,en,l,r,idx);
}
}*/
void create()
{
ll i,j;
for(i=0;i<=42;i++)
{
for(j=1;j<=n;j++)
{
seg[j][i]=seg[j-1][i];
if(a[j]&(1LL<<i))
seg[j][i]++;
}
}
}
int main()
{
//ios::sync_with_stdio(0);
//cin.tie(0);
freopen("in05.txt","r",stdin);
freopen("out05.txt","w",stdout);
ll i,j,k;
cin>>n;
po[0]=1;
for(i=1;i<=100002;i++)
{
po[i]=2*po[i-1];
po[i]%=MOD;
}
for(i=1;i<=n;i++)
{
cin>>a[i];
}
//build(1,1,n);
create();
cin>>q>>j;
while(q--)
{
cin>>l>>r;
ll cnt1,cnt0,ans=0,ans1=0;
for(i=0;i<=42;i++)
{
cnt1=seg[r][i]-seg[l-1][i];
cnt0=r-l+1-cnt1;
ans=cnt1*(cnt0*(cnt0-1))/2;
ans+=(cnt1*(cnt1-1)*(cnt1-2))/6;
ans%=MOD;
ans=ans*po[i];
ans%=MOD;
ans1+=ans;
ans1%=MOD;
}
cout<<ans1<<"\n";
}
return 0;
}
Explanation
- cnt1 stores no. of 1s occurring in i-th place of binary representation of numbers in the array from range L to R
- cnt1=seg[r][i]-seg[l-1][i];
- cnt0 stores no. of 0s occurring in i-th place of binary representation of numbers in the array from range L to R
- cnt0=r-l+1-cnt1;
- (cnt0*(cnt0-1))/2 (nC2) calculates no. of distinct pairs of 0s that can be formed from 0s present in i-th place of binary representation of numbers in the array from range L to R
- multiply no. of 1s with the no of 0-pairs calculated
- it will result in no of trios formed whose xor will give 1 (because 1 xor 0 xor 0 is 1)
ans=cnt1*(cnt0*(cnt0-1))/2;
- (cnt1*(cnt1-1)*(cnt1-2))/6 (nC3) calculates no. of distinct trios of 1s that can be formed from 0s present in i-th place of binary representation of numbers in the array from range L to R
- it will also result in no of trios formed whose xor will give 1 (because 1 xor 1 xor 1 is 1)
ans += (cnt1*(cnt1-1)*(cnt1-2))/6;
ans%=MOD;
ans=ans*po[i];
ans%=MOD;
ans1+=ans;
ans1%=MOD;