题目链接:https://www.nowcoder.com/acm/contest/148/A
题意:有函数f(x)它的值有一半概率是x - lowbit(x),一半概率是x + lowbit(x)。现在给出数组A[]对其有两种操作:①.给[L,R]区间内Ai赋值为f(A[i]);②.查询区间[L,R]内Ai和的期望。
解析:由于每个被操作的元素减和加的概率相同,所以期望值不变。直接无视操作1,直接执行操作2,问题变为简单的区间求和。
线段树代码(117ms):
#include
using namespace std;
typedef long long ll;
const ll maxN=1e5+105;
const ll mod=998244353;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll tree[maxN<<2];
ll n,m,op,x,y;
inline void pushup(ll rt)
{
tree[rt]=(tree[rt<<1]+tree[rt<<1|1])%mod;
}
void build(ll l,ll r,ll rt)
{
if(l==r)
{
scanf("%lld",&tree[rt]);
return;
}
ll m=(l+r)>>1;
build(lson);
build(rson);
pushup(rt);
}
ll sum(ll L,ll R,ll l,ll r,ll rt)
{
if(L<=l&&r<=R)
{
return tree[rt];
}
ll m=(l+r)>>1;
ll ret=0;
if(L<=m) ret=(ret+sum(L,R,lson))%mod;
if(R>m) ret=(ret+sum(L,R,rson))%mod;
pushup(rt);
return ret;
}
ll pow_mod(ll n,ll k,ll mod)//快速幂求n^k余m的结果
{
ll res=1;
n=n%mod;
while(k>0)
{
if(k&1)
res=res*n%mod;
n=n*n%mod;
k>>=1;
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
build(1,n,1);
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&op,&x,&y);
if(op==2)
{
ll ans=sum(x,y,1,n,1)%mod;
ans=ans*pow_mod(2ll,n*m,mod)%mod;
printf("%lld\n",ans%mod);
}
}
}
return 0;
}
树状数组代码(246ms):
#include
using namespace std;
typedef long long ll;
const ll MAXN=1e5+105;
const ll mod=998244353;
ll n,m,op,x,y,val,tree[MAXN];
ll lowbit(ll i)
{
return i&(-i);
}
void add(ll i,ll v)
{
while(i<=n)
{
tree[i]=(tree[i]+v)%mod;
i+=lowbit(i);
}
}
ll sum(ll i)
{
ll res=0;
while(i>0)
{
res=(res+tree[i])%mod;
i-=lowbit(i);
}
return res;
}
ll pow_mod(ll n,ll k,ll mod)//快速幂求n^k余m的结果
{
ll res=1;
n=n%mod;
while(k>0)
{
if(k&1)
res=res*n%mod;
n=n*n%mod;
k>>=1;
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&m);
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++)
{
scanf("%lld",&val);
add(i,val);
//add(i+1,-1ll*val);
}
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&op,&x,&y);
if(op==2)
{
ll ans=(sum(y)-sum(x-1)+mod)%mod;
ans=ans*pow_mod(2ll,n*m,mod)%mod;
printf("%lld\n",ans%mod);
}
}
}
return 0;
}