2018牛客网暑期ACM多校训练营(第十场)A Rikka with Lowbit (树状数组)

时间:2023-03-09 15:05:55
2018牛客网暑期ACM多校训练营(第十场)A	Rikka with Lowbit (树状数组)

链接:https://ac.nowcoder.com/acm/contest/148/A

来源:牛客网

Rikka with Lowbit

时间限制:C/C++ 5秒,其他语言10秒

空间限制:C/C++ 262144K,其他语言524288K

64bit IO Format: %lld

题目描述

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 x & (-x)x&(−x) in the template of BIT. After searching for some literature, Rikka realizes it is the implementation of the function \text{lowbit(x)}lowbit(x).

\text{lowbit}(x)lowbit(x) is defined on all positive integers. Let a1...am be the binary representation of x while a1 is the least significant digit, k be the smallest index which satisfies ak = 1. The value of \text{lowbit}(x)lowbit(x) is equal to 2k-1.

After getting some interesting properties of \text{lowbit}(x)lowbit(x), 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 x-\text{lowbit}(x)x−lowbit(x) or x+\text{lowbit}(x)x+lowbit(x), each with the probability of \frac{1}{2}

2

1



.

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 Ai to f(Ai).
  2. 2 L R, query for the expectation value of \sum_{i=L}^R A_i∑

    i=L

    R



    A

    i



    . (You may assume that each time Rikka calls f, the random variable used by f is independent with others.)

    输入描述:

    The first line contains a single integer t(1 ≤ t ≤ 3), the number of the testcases.

The first line of each testcase contains two integers n,m(1 ≤ n,m ≤ 105). 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 (w \times 2^{nm}) \mod 998244353(w×2

nm

)mod998244353.

It is easy to find that w x 2nm must be an integer.

示例1

输入

复制

1

3 6

1 2 3

1 3 3

2 1 3

1 3 3

2 1 3

1 1 3

2 1 3

输出

复制

1572864

1572864

1572864

题意:



思路:

分析会发现操作1对数字的期望根本就不会改变,于是就是一个裸的区间查询(用前缀和都可以做)(记得取模)。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define rt return
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d\n",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
inline void getInt(int* p);
const int maxn=100010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/ ll tree[maxn]; ll a[maxn]; int n,m;
int lowbit(int x)
{
return x&(-x);
}
const ll mod=998244353ll;
void add(int id,ll x)
{
while(id<=n)
{
tree[id]=(tree[id]+x)%mod;
id+=lowbit(id);
}
}
ll ask(int id)
{
ll res=0ll;
while(id)
{
res=(res+tree[id])%mod;
id-=lowbit(id);
}
return res;
}
int main()
{
//freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);
gbtb;
int t;
cin>>t;
while(t--)
{
MS0(tree);
cin>>n>>m;
repd(i,1,n)
{
cin>>a[i];
add(i,a[i]);
}
ll ans;
int op,l,r;
repd(i,1,m)
{
cin>>op>>l>>r;
if(op==1)
{
continue;
}
ans=(ask(r)-ask(l-1)+mod)%mod;
ans=(ans*powmod(2ll,1ll*n*m,mod))%mod;
cout<<ans<<endl;
}
} return 0;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '0');
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 - ch + '0';
}
}
else {
*p = ch - '0';
while ((ch = getchar()) >= '0' && ch <= '9') {
*p = *p * 10 + ch - '0';
}
}
}