[P3372][模板]线段树1

原题链接

线段树第一弹
放个板子题

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
#include<string>
#include<cstdlib>
#include<ctime>
#define MOD 1000000007
#define LL long long
using namespace std;

struct nico
{
    int lazy,l,r,len;
    LL sum;
}point[800005];

int n,a[200005],d,b,c,q,mark,i;
LL t;

void build(int lef,int rig,int p)
{
    int mid;

    point[p].l=lef;
    point[p].r=rig;
    point[p].len=rig-lef+1;

    if(lef==rig)
    {
        point[p].sum=a[lef];
        return;
    }

    mid=(lef+rig)>>1;

    build(lef,mid,p<<1);
    build(mid+1,rig,(p<<1)+1);

    point[p].sum=point[p<<1].sum+point[(p<<1)+1].sum;   
}

void pushdown(int p)
{
    point[p<<1].lazy+=point[p].lazy;
    point[(p<<1)+1].lazy+=point[p].lazy;
    point[p<<1].sum+=1ll*point[p].lazy*point[p<<1].len;
    point[(p<<1)+1].sum+=1ll*point[p].lazy*point[(p<<1)+1].len;

    point[p].lazy=0;
}

void add(int al,int ar,int x,int p)
{
    int mid,lef,rig;

    lef=point[p].l;
    rig=point[p].r;

    if(ar<lef||al>rig) return;  

    if(al==lef&&ar==rig)
    {
        point[p].lazy+=x;
        point[p].sum+=1ll*x*point[p].len;
        return;
    }

    mid=(lef+rig)>>1;

    if(point[p].lazy>0) pushdown(p);

    if(ar<=mid) add(al,ar,x,p<<1);  
    if(al>mid) add(al,ar,x,(p<<1)+1);
    if(al<=mid&&ar>mid)
    {
        add(al,mid,x,p<<1);
        add(mid+1,ar,x,(p<<1)+1);
    }

    point[p].sum=point[p<<1].sum+point[(p<<1)+1].sum;       
}

LL search(int al,int ar,int l,int r,int p)
{
    int mid;

    if(ar<l||al>r) return 0;        
    if(al==l&&ar==r) return point[p].sum;

    mid=(l+r)>>1;

    if(point[p].lazy>0) pushdown(p);    

    if(ar<=mid) return search(al,ar,l,mid,p<<1);    
    if(al>mid) return search(al,ar,mid+1,r,(p<<1)+1);
    if(al<=mid&&ar>mid) return search(al,mid,l,mid,p<<1)+search(mid+1,ar,mid+1,r,(p<<1)+1);
}

int main()
{
    scanf("%d",&n);

    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);

    build(1,n,1);

    scanf("%d",&q);

    for(i=1;i<=q;i++)
    {
        scanf("%d",&mark);

        if(mark==1)
        {
            scanf("%d%d%d",&d,&b,&c);
            add(d,b,c,1);
        }

        if(mark==2)
        {   
            scanf("%d%d",&d,&b);
            t=search(d,b,1,n,1);
            printf("%lld\n",t);         
        }
    }

    return 0;
}
ACM线段树模板C ```c #include<bits/stdc++.h> using namespace std; const int N=1e5+5;//数组开大一点 int n,m; int a[N]; struct node{ int l,r;//左右端点 int sum,lazy;//区间和和懒标记 }t[N*4]; void up(int p){//向上更新 t[p].sum=t[p<<1].sum+t[p<<1|1].sum; } void down(int p){//向下更新 if(t[p].lazy){ t[p<<1].lazy+=t[p].lazy; t[p<<1|1].lazy+=t[p].lazy; t[p<<1].sum+=t[p].lazy*(t[p<<1].r-t[p<<1].l+1); t[p<<1|1].sum+=t[p].lazy*(t[p<<1|1].r-t[p<<1|1].l+1); t[p].lazy=0; } } void build(int p,int l,int r){//建树 t[p].l=l,t[p].r=r; if(l==r){ t[p].sum=a[l]; return; } int mid=(l+r)/2; build(p<<1,l,mid); build(p<<1|1,mid+1,r); up(p); } void change(int p,int l,int r,int k){//单点修改 if(t[p].l==t[p].r){ t[p].sum=k; return; } down(p); int mid=(t[p].l+t[p].r)/2; if(r<=mid) change(p<<1,l,r,k); else if(l>mid) change(p<<1|1,l,r,k); else{ change(p<<1,l,mid,k); change(p<<1|1,mid+1,r,k); } up(p); } void add(int p,int l,int r,int k){//区间修改 if(t[p].l>=l&&t[p].r<=r){ t[p].sum+=k*(t[p].r-t[p].l+1); t[p].lazy+=k; return; } down(p); int mid=(t[p].l+t[p].r)/2; if(l<=mid) add(p<<1,l,r,k); if(r>mid) add(p<<1|1,l,r,k); up(p); } int query(int p,int l,int r){//区间查询 if(t[p].l>=l&&t[p].r<=r) return t[p].sum; down(p); int mid=(t[p].l+t[p].r)/2,ans=0; if(l<=mid) ans+=query(p<<1,l,r); if(r>mid) ans+=query(p<<1|1,l,r); return ans; } int main(){ cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; build(1,1,n); for(int i=1;i<=m;i++){ int opt,x,y,k; cin>>opt; if(opt==1){ cin>>x>>y>>k; add(1,x,y,k); } if(opt==2){ cin>>x>>y; cout<<query(1,x,y)<<endl; } if(opt==3){ cin>>x>>k; change(1,x,x,k); } } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值