思路
题目要求区间 的的所有子集的与的和。让我们来想想与有什么特殊的性质。
数据给出 不超过
,同时作为位运算的与,我们可以看看每个数的二进制的每一位有什么用。
我们知道,不同数互与操作时,二进制下每一位是互不干扰的,这就给我们一个思路了。我们可以把所有区间拆成 个区间,分别代表二进制下不同位的区间。那这和问题要问的有什么关系呢?
其实很容易发现,拆开区间后,我们一个区间子集的所有与操作和加起来其实就是这32个区间的与的和加起来。现在这 个区间分别代表的就是每一位的区间,这样计算大大简化。那么题目要求的就是
。
解释一下这式子什么意思,首先累加 个位的区间的答案(刚才说过的),接着考虑对于第
位时,如果区间有
个数是满足这意味是
的话,那么这一位子集的答案不为
的就是这
个数的随机组合,随机组合其实有
,注意取0个时不是答案,其实也就是
,而
,所以只要求出该位下区间有多少个数满足情况就可以算了。
可以用线段树维护 ,但是我线段树写炸了,用了常数更小的树状数组维护QAQ。建议预处理出
到
的
的次方数,然后
调用。
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
ll a[maxn],n,m,mx,maxv,op,c,d;
ll lg[maxn],t[32][maxn];
//struct node{
// int l,r,w;
//}t[32][maxn<<2];
char buf[1<<20],*P1=buf,*P2=buf;
//#define gc() getchar()
#define gc() (P1==P2&&(P2=(P1=buf)+fread(buf,1,1<<20,stdin),P1==P2)?EOF:*P1++)
#define TT template<class T>inline
TT void read(T&x)
{
x=0; char c=gc(); bool f=0;
while(c<48||c>57){f^=c=='-',c=gc();}
while(47<c&&c<58)x=(x<<3)+(x<<1)+(c^48),c=gc();
if(f)x=-x;
}
//ll qpow(ll a,ll b)
//{
// ll ans=1;
// while(b)
// {
// if(b&1)ans=ans*a%mod;
// b>>=1; a=a*a%mod;
// }
// return ans;
//}
//
//inline void pushup(int k,int p)
//{
// t[p][k].w=t[p][k<<1].w+t[p][k<<1|1].w;
//}
//
//inline void build(int k,int l,int r)
//{
// for(int i=0;i<=mx;i++)t[i][k].l=l,t[i][k].r=r;
// if(l==r)
// {
// for(int i=0;i<=mx;i++)t[i][k].w=(a[l]&(1<<i))>0;
// return;
// }
// int mid=l+r>>1;
// build(k<<1,l,mid);
// build(k<<1|1,mid+1,r);
// for(int i=0;i<=mx;i++)pushup(k,i);
// return;
//}
//
//inline void update(int k,int p,int u,int v)
//{
// int l=t[p][k].l,r=t[p][k].r;
// if(l==r)
// {
// t[p][k].w=v; return;
// }
// int mid=l+r>>1;
// if(u<=mid)update(k<<1,p,u,v);
// else update(k<<1|1,p,u,v);
// pushup(k,p);
// return;
//}
//
//inline int query(int k,int p,int l,int r)
//{
// int x=t[p][k].l,y=t[p][k].r;
// if(l<=x&&y<=r)return t[p][k].w;
// int mid=x+y>>1;
// int res=0;
// if(l<=mid)res+=query(k<<1,p,l,r);
// if(mid<r)res+=query(k<<1|1,p,l,r);
// return res;
//}
inline int lowbit(int x)
{
return x&(-x);
}
inline void update(int x,int p,int y)
{
for(int i=x;i<=n;i+=lowbit(i))t[p][i]+=y;
}
inline int query(int x,int p)
{
int res=0;
for(int i=x;i>=1;i-=lowbit(i))res+=t[p][i];
return res;
}
int main()
{
read(n); mx=31; lg[0]=1;
for(int i=1;i<=n;i++)
{
read(a[i]); int k=a[i],cnt=0;
while(k)
{
if(k&1)update(i,cnt,1);
k>>=1; cnt++;
}
}
for(int i=1;i<=n;i++)lg[i]=lg[i-1]*2%mod;
// build(1,1,n);
read(m);
while(m--)
{
read(op),read(c),read(d);
ll ans=0;
if(op==1)
{
for(int i=0;i<=mx;i++)
{
if((a[c]&(1<<i))!=(d&(1<<i)))
{
// update(1,i,c,(d&(1<<i))>0);
update(c,i,(d&(1<<i))>0?1:-1);
}
}
a[c]=d;
}
else
{
ll ans=0;
for(int i=0;i<=mx;i++)
{
// ans+=lg[i]*(lg[query(1,i,c,d)]-1)%mod;
ans=(ans+lg[i]*(lg[query(d,i)-query(c-1,i)]-1))%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}
京公网安备 11010502036488号