树状数组解决区间求和问题(模板)

1.改点求段模型

题目:HDU 1166 敌兵布阵

#include
#include
#include
using namespace std;
const int MAXL=50000;
int tree[MAXL+50];
int a[MAXL+50];
char s[10];
int n;
int lowbit(int k)
{
    return k&-k;
}
void update(int i,int value,int t)
{
    value*=t;
    while(i<=n)
    {
        tree[i]+=value;
        i+=lowbit(i);
    }
}
int getsum(int i)
{
    int ans=0;
    while(i>0)
    {
        ans+=tree[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    int T;
    int CASE=1;
    scanf("%d",&T);
    while(T--)
    {
        memset(tree,0,sizeof(tree));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            update(i,a[i],1);
        }
        int x,y;
        cout<<"Case "<":"<while(scanf("%s",s))
        {
            if(!strcmp(s,"End"))
                break;
            else if(!strcmp(s,"Add"))
            {
                scanf("%d%d",&x,&y);
                update(x,y,1);
            }
            else if(!strcmp(s,"Sub"))
            {
                scanf("%d%d",&x,&y);
                update(x,y,-1);
            }
            else
            {
                scanf("%d%d",&x,&y);
                int ans1=getsum(y);
                int ans2=getsum(x-1);
                cout<

2.改段求段模型
题目:POJ 3468 A Simple Problem with Integers

#include
#include
#include
using namespace std;
const int MAXL=100000;
typedef long long int LL;
LL b[MAXL+50],c[MAXL+50];
LL sum[MAXL+50];
int a[MAXL+50];
int n,m;
int lowbit(int k)
{
    return k&-k;
}
void update(LL a[],int i,int value)
{
    while(i<=n)
    {
        a[i]+=value;
        i+=lowbit(i);
    }
}

LL getsum(LL a[],int i)
{
    LL ans=0;
    while(i>0)
    {
        ans+=a[i];
        i-=lowbit(i);
    }
    return ans;
}
int main()
{
    memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));
    memset(sum,0,sizeof(sum));
    scanf("%d%d",&n,&m);
    for(int i=1; i<=n; i++)
        scanf("%d",a+i);
    for(int i=1;i<=n;i++)
        sum[i]=sum[i-1]+a[i];
    int x,y,value;
    char ch;
    int T=m;
    while(T--)
    {
        getchar();
        scanf("%c",&ch);
        if(ch=='C')
        {
            scanf("%d%d%d",&x,&y,&value);
            update(b,x,value);
            update(b,y+1,-value);
            update(c,x,value*x);
            update(c,y+1,-value*(y+1));
        }
        else if(ch=='Q')
        {
            scanf("%d%d",&x,&y);
            LL ans=0;
            ans=sum[y]-sum[x-1];
            ans+=(y+1)*getsum(b,y)-getsum(c,y);
            ans-=(x*getsum(b,x-1))-getsum(c,x-1);
            cout<

3.改点求区间最大值
题目:HDU 1754 I Hate It

#include
#include
#include
using namespace std;
const int MAXL(200000);
int tree[MAXL+50];
int a[MAXL+50];
int n,m;
int max(int a,int b)
{
    return a>b?a:b;
}
int lowbit(int k)
{
    return k&(-k);
}
void init()
{
    for(int i=1; i<=n; i++)
    {
        tree[i]=a[i];
        for(int j=1; j1)
            tree[i]=max(tree[i],tree[i-j]);
    }
}
void Update(int x)
{
    for(int i=x; i<=n; i+=lowbit(i))
    {
        tree[i]=a[i];
        for(int j=1; j1)
            tree[i]=max(tree[i],tree[i-j]);
    }
}
int Query(int x,int y)
{
    int ans=0;
    while(x<=y)
    {
        ans=max(a[y],ans);
        for(y--; y-lowbit(y)>=x; y-=lowbit(y))
            ans=max(tree[y],ans);
    }
    return ans;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=n; i++)
            scanf("%d",a+i);
        init();
        char ch;
        int x,y;
        int T=m;
        while(T--)
        {
            scanf("%c",&ch);
            if(ch=='U')
            {
                scanf("%d%d",&x,&y);
                a[x]=y;
                Update(x);
            }
            if(ch=='Q')
            {
                scanf("%d%d",&x,&y);
                int ans=Query(x,y);
                printf("%d\n",ans);
            }
        }
    }
}

你可能感兴趣的:(线段树/树状数组,一些算法模板)