線段樹模板

1.區間修改(加&&乘),區間查詢

https://www.luogu.org/problemnew/show/P3373

#include<iostream>
#include<cstdio>
#include<cstring>
#define  ll   long long
using namespace std;

struct Node
{
    long long l,r,mlz,plz,sum;
}tree[400010];
ll putnum[100010];
ll n,m,p;
void build(ll i,ll l,ll r)
{
    tree[i].l=l;tree[i].r=r;
    tree[i].plz=0;tree[i].mlz=1;
    if(l==r)
    {
        tree[i].sum=putnum[l]%p;
        return;
    }
    ll mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}
void init()
{
    scanf("%lld%lld%lld",&n,&m,&p);
    for(ll i=1;i<=n;i++) scanf("%lld",&putnum[i]);
    build(1,1,n);
}
void push_down(ll i)
{
   long long k1=tree[i].mlz,k2=tree[i].plz;
    tree[i<<1].sum=(tree[i<<1].sum*k1+k2*(tree[i<<1].r-tree[i<<1].l+1))%p;
    tree[i<<1|1].sum=(tree[i<<1|1].sum*k1+k2*(tree[i<<1|1].r-tree[i<<1|1].l+1))%p;
    tree[i<<1].mlz=(tree[i<<1].mlz*k1)%p;
    tree[i<<1|1].mlz=(tree[i<<1|1].mlz*k1)%p;
    tree[i<<1].plz=(tree[i<<1].plz*k1+k2)%p;
    tree[i<<1|1].plz=(tree[i<<1|1].plz*k1+k2)%p;
    tree[i].plz=0;
    tree[i].mlz=1;
    return ;

}
void mul(ll i,ll l,ll r,ll k)
{
    if(tree[i].r<=r && tree[i].l>=l)
    {
        tree[i].sum*=k;
        tree[i].sum%=p;
        tree[i].mlz*=k;
        tree[i].mlz%=p;
        tree[i].plz*=k;
        tree[i].plz%=p;
        return;
    }
    push_down(i);
    if(tree[i<<1].r>=l) mul(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r) mul(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}
void add(ll i,ll l,ll r,ll k)
{
    if(tree[i].r<=r && tree[i].l>=l)
    {
        tree[i].sum+=k*(tree[i].r-tree[i].l+1);
        tree[i].sum%=p;
        tree[i].plz+=k;
        tree[i].plz%=p;
        return;
    }
    push_down(i);
    if(tree[i<<1].r>=l) add(i<<1,l,r,k);
    if(tree[i<<1|1].l<=r) add(i<<1|1,l,r,k);
    tree[i].sum=(tree[i<<1].sum+tree[i<<1|1].sum)%p;
}
ll Search(ll i,ll l,ll r)
{
    if(tree[i].l>=l && tree[i].r<=r)
        return (tree[i].sum)%p;
    if(tree[i].r<l || tree[i].l>r)
        return 0;
    push_down(i);
    return (Search(i<<1,l,r)+Search(i<<1|1,l,r))%p;
}
int main()
{
    init();
    ll tag,x,y,k;
    for(ll i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&tag,&x,&y);
        if(tag==1)
        {
            scanf("%lld",&k);
            mul(1,x,y,k);
        }
        if(tag==2)
        {
            scanf("%lld",&k);
            add(1,x,y,k);
        }
        if(tag==3)
        {
            printf("%lld\n",Search(1,x,y));
        }
    }
    return 0;
}

2.單點修改,區間查詢

https://www.luogu.org/problemnew/show/P3374

#include<iostream>
#include<cstdio>
#include<cstring>
#define  ll   long long
using namespace std;
const int Maxx=500000;
struct Node
{
    int l,r,sum;
}tree[Maxx*4+50];
int putnum[Maxx+10];
int n,m;
void build(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    if(l==r)
    {
        tree[i].sum=putnum[l];
        return;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);
    build(i<<1|1,mid+1,r);
    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
void add(int i,int x,int y)
{
    if(tree[i].l==tree[i].r)
    {
        tree[i].sum+=y;
        return;
    }
    if(x<=tree[i<<1].r) add(i<<1,x,y);
    else add(i<<1|1,x,y);
    tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
int Search(int i,int l,int r)
{
    if(tree[i].l>=l && tree[i].r<=r) return tree[i].sum;
    if(tree[i].r<l || tree[i].l>r)  return 0;
    return Search(i<<1,l,r)+Search(i<<1|1,l,r);
}
void init()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        scanf("%d",&putnum[i]);
    build(1,1,n);
}
int main()
{
    init();
    int x,y,tag;
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&tag);
        scanf("%d%d",&x,&y);
        if(tag==1) add(1,x,y);
        if(tag==2) printf("%d\n",Search(1,x,y));
    }
    return 0;
}

3.區間修改(加),區間查詢

https://www.luogu.org/problemnew/show/P3372

#include<iostream>
#include<cstdio>
#include<cstring>
#define  ll   long long
using namespace std;

struct Node
{
    long long l,r,lz,sum;
}tree[400010];
ll putnum[100010];
ll n,m;
void build(ll i,ll l,ll r)
{
    tree[i].l=l;tree[i].r=r;
    tree[i].lz=0;
    if(l==r)
    {
        tree[i].sum=putnum[l];
        return;
    }
    ll mid=(l+r)>>1;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    tree[i].sum=(tree[i*2].sum+tree[i*2+1].sum);
}
void init()
{
    scanf("%lld%lld",&n,&m);
    for(ll i=1;i<=n;i++) scanf("%lld",&putnum[i]);
    build(1,1,n);
}
void push_down(ll i)
{
    if(tree[i].lz)
    {
        tree[i*2].lz+=tree[i].lz;
        tree[i*2+1].lz+=tree[i].lz;
        ll mid=(tree[i].l+tree[i].r)/2;
        tree[i*2].sum+=tree[i].lz*(mid-tree[i*2].l+1);
        tree[i*2+1].sum+=tree[i].lz*(tree[i*2+1].r-mid);
        tree[i].lz=0;
    }
}
void add(ll i,ll l,ll r,ll k)
{
    if(tree[i].r<=r && tree[i].l>=l)
    {
        tree[i].sum+=k*(tree[i].r-tree[i].l+1);
        tree[i].lz+=k;
        return;
    }
    push_down(i);
    if(tree[i*2].r>=l) add(i*2,l,r,k);
    if(tree[i*2+1].l<=r) add(i*2+1,l,r,k);
    tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
}
ll Search(ll i,ll l,ll r)
{
    if(tree[i].l>=l && tree[i].r<=r)
        return tree[i].sum;
    if(tree[i].r<l || tree[i].l>r)
        return 0;
    push_down(i);
    return Search(i*2,l,r)+Search(i*2+1,l,r);
}
int main()
{
    init();
    ll tag,x,y,k;
    for(ll i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&tag,&x,&y);
        if(tag==1)
        {
            scanf("%lld",&k);
            add(1,x,y,k);
        }
        if(tag==2)
        {
            printf("%lld\n",Search(1,x,y));
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章