POJ-3468 A Simple Problem with Integers(分块/线段树)

题意

给定 n 个数,实现两种操作:对一个区间中的数加上一个值,询问一个区间所有数的和。
1 n 100000

思路

对于区间修改查询,分块和线段树均能方便的实现,模板题不讲了。

代码

分块
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 100003
typedef long long LL;
using namespace std;

template<const int maxn>struct Block
{
    LL a[maxn],sum[maxn],tag[maxn];
    int bs,cnt;
    Block(){bs=sqrt(maxn),cnt=(maxn+bs-1)/bs;}
    void build(LL *arr,int n)
    {
        memset(sum,0,sizeof(sum));
        memset(tag,0,sizeof(tag));
        FOR(i,1,n)
        {
            a[i]=arr[i];
            sum[i/bs]+=a[i];
        }
    }
    void push_down(int _)
    {
        if(!tag[_])return;
        FOR(i,_*bs,(_+1)*bs-1)
            a[i]+=tag[_];
        tag[_]=0;
    }
    void update(int x,int y,int addval)
    {
        int kx=x/bs,ky=y/bs;
        push_down(kx),push_down(ky);
        if(kx==ky)
        {
            FOR(i,x,y)
            {
                a[i]+=addval;
                sum[kx]+=addval;
            }
            return;
        }
        for(int i=x;i<(kx+1)*bs;i++)
        {
            a[i]+=addval;
            sum[kx]+=addval;
        }
        for(int i=ky*bs;i<=y;i++)
        {
            a[i]+=addval;
            sum[ky]+=addval;
        }
        FOR(i,kx+1,ky-1)
        {
            tag[i]+=addval;
            sum[i]+=bs*addval;  
        }
    }
    LL query(int x,int y)
    {
        LL res=0;
        int kx=x/bs,ky=y/bs;
        push_down(kx),push_down(ky);
        if(kx==ky)
        {
            FOR(i,x,y)res+=a[i];
            return res;
        }
        for(int i=x;i<(kx+1)*bs;i++)
            res+=a[i];
        for(int i=ky*bs;i<=y;i++)
            res+=a[i];
        FOR(i,kx+1,ky-1)
            res+=sum[i];
        return res;
    }
};
Block<N>B;
LL a[N];

int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    FOR(i,1,n)scanf("%lld",&a[i]);
    B.build(a,n);
    FOR(i,1,q)
    {
        char c;int x,y;
        LL z;
        scanf(" %c",&c);
        if(c=='Q')
        {
            scanf("%d%d",&x,&y);
            printf("%lld\n",B.query(x,y));
        }
        else if(c=='C')
        {
            scanf("%d%d%d",&x,&y,&z);
            B.update(x,y,z);
        }
    }
    return 0;
}
线段树
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(int i=(x);i<=(y);i++)
#define DOR(i,x,y) for(int i=(x);i>=(y);i--)
#define N 100003
typedef long long LL;
using namespace std;

struct node
{
    int L,R;
    LL sum,tag;
    void add(LL x)
    {
        tag+=x;
        sum+=x*(R-L+1);
    }
};
struct SegmentTree
{
    node nd[N<<2];
    void build(int k,int L,int R,int *arr)
    {
        nd[k].L=L,nd[k].R=R,nd[k].tag=0;
        if(L==R)
        {
            nd[k].sum=arr[L];
            return;
        }
        build(k<<1,L,L+R>>1,arr);
        build(k<<1|1,(L+R>>1)+1,R,arr);
        nd[k].sum=nd[k<<1].sum+nd[k<<1|1].sum;
        return;
    }
    void push_down(int k)
    {
        if(!nd[k].tag)return;
        nd[k<<1].add(nd[k].tag);
        nd[k<<1|1].add(nd[k].tag);
        nd[k].tag=0;
        return;
    }
    void update(int k,int L,int R,LL addval)
    {
        if(L<=nd[k].L&&nd[k].R<=R)
        {
            nd[k].add(addval);
            return;
        }
        push_down(k);
        int mid=nd[k].L+nd[k].R>>1;
        if(L<=mid)update(k<<1,L,R,addval);
        if(mid<R)update(k<<1|1,L,R,addval);
        nd[k].sum=nd[k<<1].sum+nd[k<<1|1].sum;
        return;
    }
    LL query(int k,int L,int R)
    {
        if(L<=nd[k].L&&nd[k].R<=R)return nd[k].sum;
        push_down(k);
        int mid=nd[k].L+nd[k].R>>1;
        LL res=0;
        if(L<=mid)res+=query(k<<1,L,R);
        if(mid<R)res+=query(k<<1|1,L,R);
        return res;
    }
}ST;
int a[N];

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    FOR(i,1,n)scanf("%d",&a[i]);
    ST.build(1,1,n,a);
    char c;
    FOR(i,1,m)
    {
        scanf(" %c",&c);
        if(c=='Q')
        {
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%lld\n",ST.query(1,x,y));
        }
        else if(c=='C')
        {
            int x,y;
            LL z;
            scanf("%d%d%lld",&x,&y,&z);
            ST.update(1,x,y,z);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Paulliant/article/details/81186353