[模板] 树状数组

用lowbit二分构造tree,巧妙

区间更改,就是[x,n]加w,[y+1,n]减w。
Tree数组有前缀和的思想,query(x)操作就是求[1,x]的前缀和,标准的updata(x,w)是单点操作,x点+w。

//Writer:GhostCai && His Yellow Duck

#include<iostream>
using namespace std;

const int MAXN=1000000;

int n,q;
int tree[MAXN];

int lb(int x){
    return x&(-x);
}

int add(int x,int w){
    while(x<=n){
        tree[x]+=w;
        x+=lb(x);
    }
}

int ask(int x){
    int ans=0;
    while(x>0){
        ans+=tree[x];
        x-=lb(x);
    }
    return ans;
}

int main(){
    cin>>n>>q;
    int x,y,w;
    for(int i=1;i<=n;i++){
        cin>>x;
        add(i,x);
    }
    for(int i=1;i<=q;i++){
        cin>>y>>x>>w;
        if(y==1) add(x,w);
        else cout<<ask(w)-ask(x-1)<<endl; 
    }
    return 0;
}

Sylvia left me

高级操作,区间修改,常数特别小

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<iostream>
#include<cstdio>

typedef long long ll;

const int MAXN=500005;

struct file_io{
    #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
    char inbuf[1 << 25], *pin, outbuf[1 << 25], *pout;
    ll stk[20];

    file_io(): pout(outbuf) {fread(pin = inbuf, 1, 1 << 25, stdin);}
    ~file_io() {fwrite(outbuf, 1, pout - outbuf, stdout);}

    inline void getint(ll &num){
        bool neg = 0; num = 0;
        while(!isdigit(*pin)) if(*pin++ == '-') neg = 1;
        while(isdigit(*pin)) num = num * 10 + *pin++ - '0';
        if(neg) num = -num;
    }

    inline void putint(ll num){
        static ll *v = stk;
        if(!num) *pout++ = '0';
        else{
            if(num < 0) *pout++ = '-', num = -num;
            for(; num; num /= 10) *v++ = num % 10;
            while(v != stk) *pout++ = *--v + '0';
        }
    }

    inline void nextline() {*pout++ = '
';}
} fio;
#define getint(num) fio.getint(num)
#define putint(num) fio.putint(num)
#define nextline() fio.nextline()

ll sum1[MAXN],sum2[MAXN],n,m;
inline void add(ll p,ll x){for(int i=p;i<=n;i+=i&-i)sum1[i]+=x,sum2[i]+=x*p;}
inline void adds(ll l,ll r,ll x){add(l,x),add(r+1,-x);}
inline ll ask(ll p){ll res=0;for(int i=p;i; i-=i&-i)res+=(p+1)*sum1[i]-sum2[i];return res;}
inline ll asks(ll l,ll r){return ask(r)-ask(l-1);}

int main(){
    getint(n);getint(m);
    ll q,x,y,z;
    for(register int i=n;i>=1;i--)getint(x),adds(i,i,x);
    for(register int i=1;i<=m;i){
        getint(q);getint(x);getint(y); 
        if(q==1) getint(z),adds(x,y,z);
        else putint(asks(x,y)),nextline();
    }
    return 0;
}
View Code

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247489.html

原文地址:https://www.cnblogs.com/ghostcai/p/9247489.html