【模板】【线段树】

1>区间加法+区间和询问

#include<cstdio>
#include<cstdlib>
#define int long long
using namespace std;
int n,m;
const int N=1e6+3;
int d[N];
struct node
{
    int son1,son2;
    int sum,laz,len;
}tr[N<<2];
int root,cnt;
void updata(int rt)
{
    int a=tr[rt].son1 ,b=tr[rt].son2 ;
    tr[rt].sum =tr[a].sum +tr[b].sum ;
}
void build(int &rt,int l,int r)
{
    rt=++cnt;
    tr[rt].len =r-l+1;
    if(l==r) 
    {
        tr[rt].sum =d[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(tr[rt].son1 ,l,mid);
    build(tr[rt].son2 ,mid+1,r);
    updata(rt);
}
void push_down(int rt)
{
    int a=tr[rt].son1 ,b=tr[rt].son2 ,v=tr[rt].laz ;
    tr[a].laz +=v,tr[b].laz +=v;
    tr[a].sum +=v*tr[a].len ,tr[b].sum +=v*tr[b].len ;
    tr[rt].laz =0;
}
void change(int rt,int l,int r,int ll,int rr,int vv)
{
    if(ll<=l && r<=rr)
    {
        tr[rt].laz +=vv,tr[rt].sum +=tr[rt].len *vv;
        return ;
    }
    if(tr[rt].laz ) push_down(rt);
    int mid=(l+r)>>1;
    if(rr<=mid) change(tr[rt].son1 ,l,mid,ll,rr,vv);
    else if(ll>mid) change(tr[rt].son2 ,mid+1,r,ll,rr,vv);
    else change(tr[rt].son1 ,l,mid,ll,mid,vv),change(tr[rt].son2 ,mid+1,r,mid+1,rr,vv);//有影响??? 
    updata(rt);
} 
int query(int rt,int l,int r,int ll,int rr)
{
    if(ll<=l && r<=rr)
        return tr[rt].sum ;
    if(tr[rt].laz ) push_down(rt);  
    int mid=(l+r)>>1;
    if(rr<=mid) return query(tr[rt].son1 ,l,mid,ll,rr); 
    else if(ll>mid) return query(tr[rt].son2 ,mid+1,r,ll,rr);
    return query(tr[rt].son1 ,l,mid,ll,rr)+query(tr[rt].son2 ,mid+1,r,ll,rr);
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%lld",&d[i]);
    build(root,1,n);
    
    int op,ll,rr,vv;
    while(m--)
    {
        scanf("%lld%lld%lld",&op,&ll,&rr);
        if(op==1)
        {
            scanf("%lld",&vv);
            change(1,1,n,ll,rr,vv); 
        }
        else
            printf("%lld\n",query(1,1,n,ll,rr));
    }
    
    return 0;
}

2>区间加法+区间乘法+区间和询问

自设:d[i]*mul +add

#include<cstdio>
#include<cstdlib>
#define int long long
using namespace std;
int n,m,mod;
const int N=1e5+3;
int d[N],root,cnt;

struct node
{
    int son1,son2,len;
    int sum,laz,LAZ;
    //加,乘两个标记,选择d*LAZ+laz
    //add时,直接加
    //mul时,如果laz!=0,就push_down再乘
    //push_down时,如果LAZ!=1  =》  将孩子的laz,LAZ,sum都*mul
    //再处理laz 
}tr[N*3];
void updata(int rt)
{
    tr[rt].sum=(tr[tr[rt].son1].sum +tr[tr[rt].son2].sum)%mod;
} 
void build(int &rt,int l,int r)
{
    rt=++cnt;
    tr[rt].LAZ =1,tr[rt].len =r-l+1;
    if(l==r)
    {
        tr[rt].sum=d[l]%mod;
        return ;
    }
    int mid=(l+r)>>1;
    build(tr[rt].son1 ,l,mid);
    build(tr[rt].son2 ,mid+1,r);
    updata(rt);
}

void push_down(int rt)
{
    int a=tr[rt].son1 ,b=tr[rt].son2 ;
    if(tr[rt].LAZ !=1)
    {
        int t=tr[rt].LAZ ;
        tr[a].sum =(tr[a].sum *t)%mod;
        tr[a].LAZ =(tr[a].LAZ *t)%mod;
        tr[a].laz =(tr[a].laz *t)%mod;
        tr[b].sum =(tr[b].sum *t)%mod;
        tr[b].LAZ =(tr[b].LAZ *t)%mod;
        tr[b].laz =(tr[b].laz *t)%mod;
        tr[rt].LAZ =1;
    }
    if(tr[rt].laz )
    {
        int t=tr[rt].laz ;
        tr[a].sum =(tr[a].sum +t*tr[a].len )%mod;
        tr[a].laz =(tr[a].laz +t)%mod;
        tr[b].sum =(tr[b].sum +t*tr[b].len )%mod;//写掉了len... 
        tr[b].laz =(tr[b].laz +t)%mod;
        tr[rt].laz =0;
    }
}
void add(int rt,int l,int r,int ql,int qr,int v)
{
    if(ql<=l && r<=qr)
    {
        tr[rt].sum =(tr[rt].sum + v*tr[rt].len%mod)%mod;
        tr[rt].laz =(tr[rt].laz + v)%mod;
        return ;
    }
    push_down(rt);

    int mid=(l+r)>>1;
    if(qr<=mid) add(tr[rt].son1 ,l,mid,ql,qr,v);
    else if(ql>mid) add(tr[rt].son2 ,mid+1,r,ql,qr,v);
    else add(tr[rt].son1 ,l,mid,ql,mid,v),add(tr[rt].son2 ,mid+1,r,mid+1,qr,v);
    updata(rt);
}
void mul(int rt,int l,int r,int ql,int qr,int v)
{
    if(ql<=l && r<=qr)
    {
        tr[rt].sum =(tr[rt].sum *v)%mod;
        tr[rt].laz =(tr[rt].laz *v)%mod;
        tr[rt].LAZ =(tr[rt].LAZ *v)%mod;
        return ;
    }
    push_down(rt);

    int mid=(l+r)>>1;
    if(qr<=mid) mul(tr[rt].son1 ,l,mid,ql,qr,v);
    else if(ql>mid) mul(tr[rt].son2 ,mid+1,r,ql,qr,v);
    else mul(tr[rt].son1 ,l,mid,ql,qr,v),mul(tr[rt].son2 ,mid+1,r,ql,qr,v);
    updata(rt);
}

int query(int rt,int l,int r,int ql,int qr)
{
    if(ql<=l && r<=qr)
        return tr[rt].sum ;
    push_down(rt);
    int mid=(l+r)>>1;
    if(qr<=mid) return query(tr[rt].son1 ,l,mid,ql,qr);
    else if(ql>mid) return query(tr[rt].son2 ,mid+1,r,ql,qr);
    else return (query(tr[rt].son1 ,l,mid,ql,mid)+query(tr[rt].son2 ,mid+1,r,mid+1,qr))%mod;
}

signed main()
{
    scanf("%lld%lld%lld",&n,&m,&mod);
    for(int i=1;i<=n;i++)
        scanf("%lld",&d[i]);
    build(root,1,n);
    
    int op,x,y,k;
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld%lld",&op,&x,&y);
        if(op==3)
            printf("%lld\n",query(1,1,n,x,y));
        else if(op==1)
            scanf("%lld",&k),mul(1,1,n,x,y,k%mod);
        else if(op==2)
            scanf("%lld",&k),add(1,1,n,x,y,k%mod);
    }
    
    return 0;
} 

 3>离散+统计线段数

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m;
const int N=100003;
int op[N][4];//l,r,op,v
struct node
{
    int d,id,wz;
    bool operator < (const node & o) const 
    {
        return d<o.d;
    }
}d[N*2];
void ls()
{
    scanf("%d %d",&n,&m);
    char s[10];int l,r,v;
    for(int i=0;i<m;i++)
    {
        scanf("%s %d %d",s,&l,&r);
        if(l>r) swap(l,r);
        op[i][0]=l,op[i][1]=r;
        if(s[0]=='C')
            scanf("%d",&v),op[i][2]=1,op[i][3]=v;
        d[i*2].d =l,d[i*2+1].d =r;
        d[i*2].id =d[i*2+1].id =i;
        d[i*2].wz =0,d[i*2+1].wz =1;
    }
    sort(d,d+2*m);
    int last=0,w=0;
    for(int i=0;i<2*m;i++)
    {
        if(d[i].d !=last)
        {
            w++;
            if(d[i].d >last+1) w++;
            last=d[i].d ;
            op[d[i].id ][d[i].wz ]=w;
        }
        else
            op[d[i].id ][d[i].wz ]=w;
    }
    n=w;
}
int root,tot;
struct no
{
    int l,r,lc,rc,col;
    bool flag;//true为纯色 
}tree[N*3];
void updata(int rt)
{
    int lc=tree[rt].lc ,rc=tree[rt].rc ;
    if(tree[lc ].flag && tree[rc ].flag && tree[lc ].col ==tree[rc ].col )
        tree[rt].flag =true,tree[rt].col =tree[lc ].col ;
}
void create(int &rt,int l,int r)
{
    rt=tot++;
    tree[rt].l =l,tree[rt].r =r;
    tree[rt].lc =tree[rt].rc =-1;
    tree[rt].flag =true;
    if(l==r)
        tree[rt].col =1;
    else
    {
        int mid=(l+r)/2;
        create(tree[rt].lc ,l,mid);
        create(tree[rt].rc ,mid+1,r);
        updata(rt);
    }
}
void pushdown(int rt)
{
    int lc=tree[rt].lc ,rc=tree[rt].rc ;
    tree[lc].flag =tree[rc].flag =true;
    tree[lc].col =tree[rc].col =tree[rt].col ;
    tree[rt].flag =false;
}
void change(int rt,int l,int r,int v)
{
    int ll=tree[rt].l ,rr=tree[rt].r;
    if(l<=ll&&rr<=r)
        tree[rt].flag =true,tree[rt].col =v;
    else
    {
        if(tree[rt].flag ) pushdown(rt);
        int mid=(ll+rr)/2;
        if(r<=mid) change(tree[rt].lc ,l,r,v);
        else
            if(l>mid) change(tree[rt].rc ,l,r,v);
            else
                change(tree[rt].lc ,l,mid,v),
                change(tree[rt].rc ,mid+1,r,v);
    }
}
bool f[53];
void dfs(int rt,int l,int r)
{
    if(tree[rt].flag )
        f[tree[rt].col ]=true;
    else
    {
        int ll=tree[rt].l ,rr=tree[rt].r ;
        int mid=(ll+rr)/2;
        if(r<=mid)  dfs(tree[rt].lc ,l,r);
        else
            if(l>mid) dfs(tree[rt].rc ,l,r);
            else dfs(tree[rt].lc ,l,mid),dfs(tree[rt].rc ,mid+1,r);
    }
}
int main()
{
    ls();
    create(root,1,n);
    for(int i=0;i<m;i++)
    {
        if(op[i][2]==1)
            change(root,op[i][0],op[i][1],op[i][3]);
        else
        {
            memset(f,false,sizeof(f));
            dfs(root,op[i][0],op[i][1]);
            int ans=0;
            for(int i=0;i<=50;i++)
                if(f[i]) ans++;
            printf("%d\n",ans);
        }
    }
    return 0;
} 

 

posted @ 2019-09-29 17:14  心若笺诗  阅读(138)  评论(0编辑  收藏  举报