洛谷 P3373 模板线段树 2

Posted 一蓑烟雨任生平

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 P3373 模板线段树 2相关的知识,希望对你有一定的参考价值。

题目描述

如题,已知一个数列,你需要进行下面三种操作:

1.将某区间每一个数乘上x

2.将某区间每一个数加上x

3.求出某区间每一个数的和

输入输出格式

输入格式:

 

第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

接下来M行每行包含3或4个整数,表示一个操作,具体如下:

操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

 

输出格式:

 

输出包含若干行整数,即为所有操作3的结果。

 

输入输出样例

输入样例#1: 复制
5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4
输出样例#1: 复制
17
2

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=8,M<=10

对于70%的数据:N<=1000,M<=10000

对于100%的数据:N<=100000,M<=100000

(数据已经过加强^_^)

样例说明:

技术分享图片

故输出应为17、2(40 mod 38=2)

思路:线段树的区间加法和区间乘法和区间查询。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100001
using namespace std;
struct nond{
    long long l,r,sum;
    long long flag1,falg2;
}tree[MAXN*4];
long long n,m,p;
void up(long long now){
    tree[now].sum=(tree[now*2].sum+tree[now*2+1].sum)%p;
}
void build(long long now,long long l,long long r){
    tree[now].l=l;tree[now].r=r;
    tree[now].flag1=1;tree[now].falg2=0;
    if(tree[now].l==tree[now].r){
        scanf("%d",&tree[now].sum);
        return ;
    }
    long long mid=(tree[now].l+tree[now].r)/2;
    build(now*2,l,mid);
    build(now*2+1,mid+1,r);
    up(now);
}
void down(long long now){
    if(tree[now].flag1!=1){
        tree[now*2].flag1=tree[now*2].flag1*tree[now].flag1%p;
        tree[now*2].falg2=tree[now*2].falg2*tree[now].flag1%p;
        tree[now*2].sum=tree[now*2].sum*tree[now].flag1%p;
        tree[now*2+1].flag1=tree[now*2+1].flag1*tree[now].flag1%p;
        tree[now*2+1].falg2=tree[now*2+1].falg2*tree[now].flag1%p;
        tree[now*2+1].sum=tree[now*2+1].sum*tree[now].flag1%p;
        tree[now].flag1=1;
    }
    if(tree[now].falg2){
        tree[now*2].falg2=(tree[now*2].falg2+tree[now].falg2)%p;
        tree[now*2+1].falg2=(tree[now*2+1].falg2+tree[now].falg2)%p;
        tree[now*2].sum=(tree[now*2].sum+(tree[now*2].r-tree[now*2].l+1)*tree[now].falg2%p)%p;
        tree[now*2+1].sum=(tree[now*2+1].sum+(tree[now*2+1].r-tree[now*2+1].l+1)*tree[now].falg2%p)%p;
        tree[now].falg2=0;
    }
}
void changechen(long long now,long long l,long long r,long long k){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].sum=tree[now].sum*k%p;
        tree[now].flag1=tree[now].flag1*k%p;
        tree[now].falg2=tree[now].falg2*k%p;
        return ;    
    }
    if(tree[now].flag1!=1||tree[now].falg2)    down(now);
    long long mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    changechen(now*2,l,r,k);
    else if(l>mid)    changechen(now*2+1,l,r,k);
    else{
        changechen(now*2,l,mid,k);
        changechen(now*2+1,mid+1,r,k);
    }
    up(now);
}
void changeadd(long long now,long long l,long long r,long long k){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].sum=(tree[now].sum+(tree[now].r-tree[now].l+1)*k%p)%p;
        tree[now].falg2=(tree[now].falg2+k)%p;
        return ;    
    }
    if(tree[now].flag1!=1||tree[now].falg2)    down(now);
    long long mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    changeadd(now*2,l,r,k);
    else if(l>mid)    changeadd(now*2+1,l,r,k);
    else{
        changeadd(now*2,l,mid,k);
        changeadd(now*2+1,mid+1,r,k);
    }
    up(now);
}
long long query(long long now,long long l,long long r){
    if(tree[now].l==l&&tree[now].r==r)
        return tree[now].sum%p;
    if(tree[now].flag1!=1||tree[now].falg2)    down(now);
    long long mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    return query(now*2,l,r);
    else if(l>mid)    return query(now*2+1,l,r);
    else    return (query(now*2,l,mid)+query(now*2+1,mid+1,r))%p;
}
int main(){
    scanf("%lld%lld%lld",&n,&m,&p);
    build(1,1,n);
    for(long long i=1;i<=m;i++){
        long long opt,x,y,k;
        scanf("%lld%lld%lld",&opt,&x,&y);
        if(opt==1){
            scanf("%lld",&k);
            changechen(1,x,y,k);
        }
        else if(opt==2){
            scanf("%lld",&k);
            changeadd(1,x,y,k);
        }
        else if(opt==3)    printf("%lld\n",query(1,x,y)%p);
    }
}

 

以上是关于洛谷 P3373 模板线段树 2的主要内容,如果未能解决你的问题,请参考以下文章

原创洛谷 LUOGU P3373 模板线段树2

洛谷P3373 模板线段树 2

P3373 模板线段树 2 (未完待续)

P3373 模板线段树 2

P3373 模板线段树 2 {线段树,模板}

P3373 模板线段树 2