目录
Description
有三种操作
$1\ l\ r: $ 区间查询和值
$2\ l\ r: $ 将区间上的每个数都减去其 \(lowbit\)
$3\ l\ r: $ 将区间上的每个数都加上其 \(upbit\)
State
\(1<=n<=10^{5}\)
\(T<=5\)
\(1<=a[i]<=10^9\)
\(1<=q<=10^5\)
Input
1
5
5 2 2 9 7
4
2 1 5
1 1 1
3 1 3
1 2 5
Output
4
14
Solution
这个题的基本思路还是很好想的,\(2\) 操作单点更新就可以;
\(3\) 操作如果仍然单点更新,只有等到这个区间上所有的数都为 \(2^k\) 时才可以区间更新,而且在此之前的单点更新都要寻找对应的 \(upbit\) ,不妨操作有些繁琐,如果 \(3\) 操作本身的值就是 \(2^k\) 就可以进行区间更新简化时间了
所以将 \(a[i]\) 分成 \(upbit\) 和 \(a[i]-upbit\) 分别操作就可以了
Code
const int N = 1e5 + 5;
int n, m, _, k;
int a[N];
ll ksm(ll a, ll x);
struct Node
{
int l, r;
ll maxx, minn;
int lazy;
#define lson id << 1
#define rson id << 1 | 1
void update(int x)
{
lazy += x;
maxx = maxx * ksm(2, x) % mod;
}
}t[N << 2];
vector<int> v;
ll ksm(ll a, ll x)
{
ll ans = 1;
while(x){
if(x & 1) ans = ans * a % mod;
a = a * a % mod;
x >>= 1;
}
return ans;
}
void push_up(int id)
{
t[id].maxx = (t[lson].maxx + t[rson].maxx) % mod;
t[id].minn = (t[lson].minn + t[rson].minn) % mod;
}
void push_down(int id)
{
int x = t[id].lazy;
if(x){
t[lson].update(x);
t[rson].update(x);
t[id].lazy = 0;
}
}
void build(int l, int r, int id)
{
t[id].l = l, t[id].r = r;
t[id].lazy = 0;
if(l == r){
int pos = upper_bound(v.begin(), v.end(), a[l]) - v.begin() - 1;
t[id].maxx = v[pos];
t[id].minn = a[l] - v[pos];
}
else{
int mid = l + r >> 1;
build(l, mid, lson);
build(mid + 1, r, rson);
push_up(id);
}
}
ll query(int l, int r, int id)
{
int L = t[id].l, R = t[id].r;
if(L >= l && r >= R){
return (t[id].minn + t[id].maxx) % mod;
}
else{
int mid = L + R >> 1;
push_down(id);
ll ans = 0;
if(mid >= l) ans = (ans + query(l, r, lson)) % mod;
if(r >= mid + 1) ans = (ans + query(l, r, rson)) % mod;
push_up(id);
return ans;
}
}
void update(int l, int r, int id) //+
{
int L = t[id].l, R = t[id].r;
if(L >= l && r >= R){
t[id].update(1);
}
else{
int mid = L + R >> 1;
push_down(id);
if(mid >= l) update(l, r, lson);
if(r >= mid + 1) update(l, r, rson);
push_up(id);
}
}
void modify(int l, int r, int id) //-
{
int L = t[id].l, R = t[id].r;
if(L >= l && r >= R && t[id].maxx == 0){
return ;
}
if(L == R){
if(t[id].minn == 0){
t[id].maxx = 0;
return ;
}
t[id].minn = t[id].minn - lowbit(t[id].minn);
return ;
}
{
int mid = L + R >> 1;
push_down(id);
if(mid >= l) modify(l, r, lson);
if(r >= mid + 1) modify(l, r, rson);
push_up(id);
}
}
signed main()
{
//IOS;
for(int i = 0; i < 31; i ++){
v.pb(1 << i);
}
rush(){
sd(n);
rep(i, 1, n) sd(a[i]);
build(1, n, 1);
sd(m);
int l, r, opt;
while(m --> 0){
sddd(opt, l, r);
if(opt == 1){
ll ans = query(l, r, 1);
pll(ans);
}
else if(opt == 2){
modify(l, r, 1);
}
else{
update(l, r, 1);
}
}
}
//PAUSE;
return 0;
}