树状数组的神操作QAQ

卧槽

厉害了,我的树状数组

 

1、单点修改,单点查询

  用差分数组维护

#include<cstdio>
#include<iostream>
using namespace std;
#define int long long
#define M 1000500
#define lowbit(x) (x&(-x))
int c[M],flag,n,m;
inline void add(int pos,int x)
{
    for(int i=pos;i<=n;i+=lowbit(i))
        c[i]+=x;
}
inline int query(int x)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int now=0,last=0;
    for(int i=1;i<=n;i++)
    {
        cin>>now;
        add(i,now-last);
        last=now;
    }
    int x;
    for(int i=1;i<=m;i++)
    {
        cin>>flag;
        if(flag==1)
        {
            int x,k;
            cin>>x>>k;
            add(x,k);
            add(x+1,-k);
        }
        else
        {
            cin>>x;
            cout<<query(x)<<endl;
        }
    }
    return 0;
}
    

 

 

2、单点修改,区间查询(最原始的,最本质的)

 

#include<cstdio>
#include<iostream>
using namespace std;
#define N 1000050
#define int long long 
int a[N],c[N],j;
int n,m;
inline int lowbit(int x)
{
    return x&(-x);
}
inline void add(int x,int y)
{
    while(x<=n)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}
inline int sum(int x)
{
    int ace=0;
    while(x>=1)
    {
        ace+=c[x];
        x-=lowbit(x);
    }
    return ace;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int x,y;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        add(i,a[i]);
    }
    for(int i=1;i<=m;i++)
    {
        cin>>j>>x>>y;
        if(j==1)
            add(x,y);
        else
            cout<<sum(y)-sum(x-1)<<endl;
    }
    return 0;
    
}

 

 

3、区间修改,单点查询

  差分应用

 

#include<cstdio>
#include<iostream>
using namespace std;
#define int long long
#define M 1000500
#define lowbit(x) (x&(-x))
int c[M],flag,n,m;
inline void add(int pos,int x)
{
    for(int i=pos;i<=n;i+=lowbit(i))
        c[i]+=x;
}
inline int query(int x)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int now=0,last=0;
    for(int i=1;i<=n;i++)
    {
        cin>>now;
        add(i,now-last);
        last=now;
    }
    int x;
    for(int i=1;i<=m;i++)
    {
        cin>>flag;
        if(flag==1)
        {
            int x,y,k;
            cin>>x>>y>>k;
            add(x,k);
            add(y+1,-k);
        }
        else
        {
            cin>>x;
            cout<<query(x)<<endl;
        }
    }
    return 0;
}
    

 

 

4、区间修改,区间查询(niubilitiful)

 

观察式子:
a[1]+a[2]+...+a[n]

= (c[1]) + (c[1]+c[2]) + ... + (c[1]+c[2]+...+c[n]) 

= n*c[1] + (n-1)*c[2] +... +c[n]

= n * (c[1]+c[2]+...+c[n]) - (0*c[1]+1*c[2]+...+(n-1)*c[n])    (式子①)

那么我们就维护一个数组c2[n],其中c2[i] = (i-1)*c[i]

每当修改c的时候,就同步修改一下c2,这样复杂度就不会改变

那么

式子①

$=n*\sum{(c,n)} - \sum{(c2,n)}$

于是我们做到了在O(logN)的时间内完成一次区间和查询

 

#include<cstdio>
#include<iostream>
using namespace std;
#define int long long
#define M 1000500
#define lowbit(x) (x&(-x))
int c[M],flag,n,m;
int s[M];
inline void add(int pos,int x)
{
    for(int i=pos;i<=n;i+=lowbit(i))
    {
        c[i]+=x;
        s[i]+=(pos-1)*x;
    }    
}
inline int queryc(int x)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=c[i];
    return ans;
}
inline int querys(int x)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        ans+=s[i];
    return ans;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int now=0,last=0;
    for(int i=1;i<=n;i++)
    {
        cin>>now;
        add(i,now-last);
        last=now;
    }
    for(int i=1;i<=m;i++)
    {
        cin>>flag;
        if(flag==1)
        {
            int x,y,k;
            cin>>x>>y>>k;
            add(x,k);
            add(y+1,-k);
        }
        else
        {
            int x,y;
            cin>>x>>y;
            int tot1=y*queryc(y)-querys(y);
            int tot2=(x-1)*queryc(x-1)-querys(x-1);
            cout<<tot1-tot2<<endl;
        }
    }
    return 0;
}
    

一件很好的事情就是树状数组的常数比其他NlogN的数据结构小得多,实际上它的计算次数比NlogN要小很多,再加上它代码短,是OI中的利器

厉害了~~~~~

 

posted @ 2018-08-08 13:16  olinr  阅读(151)  评论(0编辑  收藏  举报