码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷 P3373 【模板】线段树 2

时间:2018-03-24 11:32:58      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:输入输出格式   toolbar   一个   range   return   gpo   数据规模   problem   加强   

题目描述

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

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

标签:输入输出格式   toolbar   一个   range   return   gpo   数据规模   problem   加强   

原文地址:https://www.cnblogs.com/cangT-Tlan/p/8637881.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!