链接:https://www.nowcoder.com/acm/contest/148/A
来源:牛客网
题目描述
Today, Rikka is going to learn how to use BIT to solve some simple data structure tasks. While studying, She finds there is a magic expression
in the template of BIT. After searching for some literature, Rikka realizes it is the implementation of the function
.
is defined on all positive integers. Let a
1...a
m be the binary representation of x while a
1 is the least significant digit, k be the smallest index which satisfies a
k = 1. The value of
is equal to 2
k-1.
After getting some interesting properties of
, Rikka sets a simple data structure task for you:
At first, Rikka defines an operator f(x), it takes a non-negative integer x. If x is equal to 0, it will return 0. Otherwise it will return
or
, each with the probability of
.
Then, Rikka shows a positive integer array A of length n, and she makes m operations on it.
There are two types of operations:
1. 1 L R, for each index i ∈ [L,R], change A i to f(A i).
2. 2 L R, query for the expectation value of
. (You may assume that each time Rikka calls f, the random variable used by f is independent with others.)
![](https://i-blog.csdnimg.cn/blog_migrate/0b78479da1c2359d84edf55d2d98c48e.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7d6bf2cf71a8ed68d9a8911367663cc9.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2266d9163945df50fc7c2f3d5df78d65.png)
![](https://i-blog.csdnimg.cn/blog_migrate/2266d9163945df50fc7c2f3d5df78d65.png)
After getting some interesting properties of
![](https://i-blog.csdnimg.cn/blog_migrate/2266d9163945df50fc7c2f3d5df78d65.png)
At first, Rikka defines an operator f(x), it takes a non-negative integer x. If x is equal to 0, it will return 0. Otherwise it will return
![](https://i-blog.csdnimg.cn/blog_migrate/c96959f3584bd67f68e560b468e2f563.png)
![](https://i-blog.csdnimg.cn/blog_migrate/8765fab38f09d0e6728fb3c27a05a8ed.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7dd5ec0f90a6df29dd5aa8d440a119e5.png)
Then, Rikka shows a positive integer array A of length n, and she makes m operations on it.
There are two types of operations:
1. 1 L R, for each index i ∈ [L,R], change A i to f(A i).
2. 2 L R, query for the expectation value of
![](https://i-blog.csdnimg.cn/blog_migrate/e4b13ed6d44d86dcb4bcfae76ea90f7d.png)
输入描述:
The first line contains a single integer t(1 ≤ t ≤ 3), the number of the testcases.5
The first line of each testcase contains two integers n,m(1 ≤ n,m ≤ 10
). The second line contains n integers Ai
(1 ≤ Ai
≤ 108
).
And then m lines follow, each line contains three integers t,L,R(t ∈ {1,2}, 1 ≤ L ≤ R ≤ n).
输出描述:
For each query, let w be the expectation value of the interval sum, you need to output
![](https://i-blog.csdnimg.cn/blog_migrate/32f65ee526d42605b25cc0576bf2009e.png)
.nm
It is easy to find that w x 2
must be an integer.
示例1
输出
复制1572864 1572864 1572864
分析:每次变化+-lowbit得到的期望是原结果,所以我们直接求一下区间和就可以
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
const ll mod = 998244353;
ll qp(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll array1[maxn];
struct node1
{
ll sum,addmark;
} Node[maxn<<2];
void pushup(int node)
{
Node[node].sum=Node[node<<1].sum+Node[node<<1|1].sum;
}
void buildtree(int node,int left,int right)
{
Node[node].addmark=0;
if(left==right)
{
Node[node].sum=array1[left];
return;
}
int m=(left+right)>>1;
buildtree(node<<1,left,m);
buildtree(node<<1|1,m+1,right);
pushup(node);
}
void pushdown(int node,int left,int right)
{
if(Node[node].addmark)
{
int m=(left+right)>>1;
Node[node<<1].addmark+=Node[node].addmark;
Node[node<<1|1].addmark+=Node[node].addmark;
Node[node<<1].sum+=(m-left+1)*Node[node].addmark;
Node[node<<1|1].sum+=(right-m)*Node[node].addmark;
Node[node].addmark=0;
}
}
ll query(int node,int begin,int end,int left,int right)
{
if(left<=begin&&right>=end)
return Node[node].sum;
pushdown(node,begin,end);
int m=(begin+end)>>1;//小心!!
ll ans=0;
if(left<=m)
ans+=query(node<<1,begin,m,left,right);
if(right>m)
ans+=query(node<<1|1,m+1,end,left,right);
return ans;
}
void update(int node,int add,int begin,int end,int left,int right)
{
if(begin>=left&&end<=right)
{
Node[node].sum+=(end-begin+1)*add;
Node[node].addmark+=add;
return;
}
int m=(begin+end)>>1;//小心!!
pushdown(node,begin,end);
if(left<=m)
update(node<<1,add,begin,m,left,right);
if(right>m)
update(node<<1|1,add,m+1,end,left,right);
pushup(node);
}
ll n,m;
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int i,j,k,t;
cin>>t;
while(t--)
{
cin>>n>>m;
for(i=1; i<=n; i++) cin>>array1[i];
buildtree(1,1,n);
for(i=1; i<=m; i++)
{
int a,b,c;
cin>>a>>b>>c;
if(a==2) cout<<query(1,1,n,b,c)%mod*qp(2,n*m)%mod<<endl;
}
}
return 0;
}