树状数组

来源:互联网 发布:新倩女幽魂辅助软件 编辑:程序博客网 时间:2024/05/16 18:43

树状数组模板

树状数组的应用:

  • 单点更新-区间查询
  • 区间更新-单点查询
  • 区间更新-区间查询

一、单点更新-区间查询

题目链接:NYO116 士兵杀敌(二)
题目描述

代码:

#include<cstdio>#include<cstring>int sum[2000000+2];int n,m; inline int lowerbit(int x){    return x&-x;    //return x-(x&(x-1));}void UpDate(int x,int y){    while(x<=n)    {        sum[x]+=y;        x+=lowerbit(x);    }}int  query(int x){    int ans=0;    while(x>0)    {        ans+=sum[x];        x-=lowerbit(x);    }    return ans;}int main(){    memset(sum,0,sizeof(sum));    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        int t;        scanf("%d",&t);        UpDate(i,t);    }    char str[10];    int l,r;    while(m--)    {        scanf("%s%d%d",&str,&l,&r);        if(str[0]=='Q')        {            printf("%d\n",query(r)-query(l-1));        }        else        {            UpDate(l,r);        }       }    return 0;}        

二、区间更新-单点查询

题目链接:HDU1556 Color the ball
题目描述
代码:

//差分数组的理解#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int MAXN=100010;int c[MAXN];int n;int lowbit(int x){    return x&(-x);}void addd(int i,int val){    while(i<=n)    {        c[i]+=val;        i+=lowbit(i);    }}int sum(int i){    int s=0;    while(i>0)    {        s+=c[i];        i-=lowbit(i);    }    return s;}int main(){    int l,r;    while(scanf("%d",&n),n)    {        memset(c,0,sizeof(c));        for(int i=0;i<n;i++)        {            scanf("%d%d",&l,&r);            add(l,1);            add(r+1,-1);        }        for(int i=1;i<n;i++)          printf("%d ",sum(i));        printf("%d\n",sum(n));    }    return 0;}

三、区间更新-区间查询

题目链接:POJ 3468 A Simple Problem with Integers
题目描述
代码:

#include<cstdio>#include<cstring> #define ll long long int#define lowerbit(x) (x&-x)const int maxn=100000+5; int n,q;ll sum[maxn];//原始数组前缀和 ll c1[maxn],c2[maxn];void add(int i,int x){    int pos=i;    while(pos<=n)    {        c1[pos]+=x;        c2[pos]+=i*x;        pos+=lowerbit(pos);    }}ll query(ll x){    ll ans=0;    int i=x;    while(i>0)    {        ans+=(x+1)*c1[i]-c2[i];        i-=lowerbit(i);    }    return ans;}int main(){    scanf("%d%d",&n,&q);    memset(sum,0,sizeof(sum));    memset(c1,0,sizeof(c1));    memset(c2,0,sizeof(c2));    for(int i=1;i<=n;i++)    {        ll t;        scanf("%lld",&t);        sum[i]=sum[i-1]+t;     }     char str[4];     int l,r,p;    for(int i=0;i<q;i++)    {        scanf("%s",str);        if(str[0]=='Q')        {            scanf("%d%d",&l,&r);            printf("%lld\n",sum[r]-sum[l-1]+query(r)-query(l-1));        }        else        {            scanf("%d%d%d",&l,&r,&p);            add(l,p);            p=-p;            add(r+1,p);        }    }return 0; }

参考

  • 树状数组:维基百科
  • 差分数组概述
  • 树状数组:区间修改-区间查询
原创粉丝点击