HDU7116 Lowbit(线段树)

目录

Description

有两种操作:

\(1 \ L\ R\):对于每个数 \(a[i]=a[i]+lowbit(a[i])\)

\(2 \ L\ R\):查询区间 \([L,R]\) 的值

State

\(1<=T<=20\)

\(1<=n<=10^{5}\)

\(1<=m<=10^5\)

\(1<=a[i]<=998244353\)

Input

1
5
1 2 3 4 5
5
2 2 4
1 1 3
2 2 4
1 1 5
2 4 5

Output

9
12
14

Solution

这道题目是我遇到过最神奇的问题了,不懂就问,不将 \(mod=998244353\) 置为 \(cosnt\)\(T\) 掉(求解释)

如果没有求余运算,思路其实挺好想的,当一个数的二进制形式 是这样时 \(1010101010...10\) ,它需要一步一步的加上对应的 \(lowbit\), 而一旦变为 \(2\) 的倍数,这个区间只需要 \(×2\) 就可以了

Code

const ll mod = 998244353;
const int N = 1e5 + 5;

    ll n, m, _;
    int i, j, k;
    ll a[N];

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;
}

    struct Node
    {
        int l, r;
        ll sum, lazy;
        bool tag;
        #define lson id << 1
        #define rson id << 1 | 1
        void update(ll x)
        {
            sum = (sum * ksm(2, x)) % mod;
            lazy = (x + lazy) % mod;
        }
    }t[N << 2];

void push_up(int id)
{
    t[id].sum = (t[lson].sum + t[rson].sum) % mod;
    t[id].tag = (t[lson].tag && t[rson].tag);
}

void push_down(int id)
{
    ll 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].sum = t[id].lazy = t[id].tag = 0;
    if(l == r){
        t[id].sum = a[l];
        t[id].tag = (t[id].sum == lowbit(t[id].sum));
    }
    else{
        int mid = l + r >> 1;
        build(l, mid, lson);
        build(mid + 1, r, rson);
        push_up(id);
    }
    return void();
}

void update(int l, int r, int id)
{
    int L = t[id].l, R = t[id].r;
    if(L >= l && r >= R && t[id].tag){
        return t[id].update(1), void();
    }
    if(L == R){
        t[id].sum += lowbit(t[id].sum);
        return t[id].tag = (t[id].sum == lowbit(t[id].sum)), void();
    }
    push_down(id);
    int mid = L + R >> 1;
    if(mid >= l) update(l, r, lson);
    if(r >= mid + 1) update(l, 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].sum;
    } 
    else{
        int mid = L + R >> 1;
        ll ans = 0;
        push_down(id);
        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;
    }
}

signed main()
{
    //IOS;
    rush(){
        sd(n);
        rep(i, 1, n) sll(a[i]);
        build(1, n, 1);
        sd(m);
        rep(i, 1, m){
            int opt, l, r;
            sddd(opt, l, r);
            if(opt == 1){
                update(l, r, 1);
            }
            else{
                ll ans = query(l, r, 1);
                pll(ans);
            }
        }
    }
    //PAUSE;
    return 0;
}
posted @ 2021-09-08 16:35  Bcoi  阅读(82)  评论(0)    收藏  举报