luoguP3373 【模板】线段树 2

P3373 【模板】线段树 2

    • 969通过
    • 3.9K提交
  • 题目提供者 HansBug
  • 标签 云端↑
  • 难度 提高+/省选-
  • 时空限制 1s / 128MB

题目描述

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

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)

思路:

  线段树模板

坑点:

  1)在更新加的时候要记得看一下爸爸的乘,必须先乘上再进行加

  2)一定要随时记得%p!!!

上代码=u=:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define LL long long
#define lson (l+r)<<1
#define rson (l+r)<<1|1
using namespace std;

const int M = 100100;
LL n,m,sum,p;
LL ci[M];

struct C {
    LL l,r;
    LL add,multiply;
    LL w;
}t[M*4];

LL readin()
{
    LL f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9')
    {if(ch=='-') f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0')
    {x=x*10+ch-'0',ch=getchar();}
    return (LL)x*f;
}

void builds(LL l,LL r,LL k)
{
    t[k].l=l,t[k].r=r;
    t[k].add=0,t[k].multiply=1;
    if(l==r)
    {
        t[k].w=ci[l];
        return;
    }
    LL mid=(l+r)>>1;
    builds(l,mid,lson),builds(mid+1,r,rson);
    t[k].w=(t[lson].w+t[rson].w)%p;
}

void down(LL k)
{
    LL l=t[k].l,r=t[k].r;
    t[lson].add=(t[lson].add*t[k].multiply+t[k].add)%p;
    t[rson].add=(t[rson].add*t[k].multiply+t[k].add)%p;
    t[lson].multiply=(t[lson].multiply*t[k].multiply)%p;
    t[rson].multiply=(t[rson].multiply*t[k].multiply)%p;
    t[lson].w=(t[k].add*(t[lson].r-t[lson].l+1)%p+t[lson].w*t[k].multiply%p)%p;
    t[rson].w=(t[k].add*(t[rson].r-t[rson].l+1)%p+t[rson].w*t[k].multiply%p)%p;
    t[k].add=0,t[k].multiply=1;
}

void Multiply(LL a,LL b,LL k,LL cheng)
{
    if(a<=t[k].l && t[k].r<=b)
    {
        t[k].w=t[k].w*cheng%p;
        t[k].add=t[k].add*cheng%p;
        t[k].multiply=t[k].multiply*cheng%p;
        return;
    }
    down(k);
    LL l=t[k].l,r=t[k].r;
    LL mid=(l+r)>>1;
    if(a<=mid) Multiply(a,b,lson,cheng);
    if(b>mid)  Multiply(a,b,rson,cheng);
    t[k].w=(t[lson].w+t[rson].w)%p;
}

void Add(LL a,LL b,LL k,LL jia)
{
    if(a<=t[k].l && t[k].r<=b)
    {
        t[k].add=(t[k].add+jia)%p;
        t[k].w=(t[k].w+jia*(t[k].r-t[k].l+1))%p;
        return;
    }
    down(k);
    LL l=t[k].l,r=t[k].r;
    LL mid=(l+r)>>1;
    if(a<=mid) Add(a,b,lson,jia);
    if(b>mid)  Add(a,b,rson,jia);
    t[k].w=(t[lson].w+t[rson].w)%p;
}

LL Sum(LL a,LL b,LL k)
{
    if(a<=t[k].l && t[k].r<=b)
        return t[k].w%p;
    down(k);
    LL ans=0;
    LL l=t[k].l,r=t[k].r;
    LL mid=(l+r)>>1;
    if(a<=mid) ans=Sum(a,b,lson)%p;
    if(b>mid) ans+=Sum(a,b,rson)%p;
    return ans%p;
}

int main()
{
    n=readin(),m=readin(),p=readin();
    for(int i=1;i<=n;i++)
        ci[i]=readin();
    builds(1,n,1);
    LL a,b,v;
    for(int i=1,q;i<=m;i++)
    {
        scanf("%d",&q);
        switch(q)
        {
            case 1:
                a=readin(),b=readin(),v=readin();
                Multiply(a,b,1,v%p);
                break;
            case 2:
                a=readin(),b=readin(),v=readin();
                Add(a,b,1,v%p);
                break;
            default:
                a=readin(),b=readin();
                sum=Sum(a,b,1)%p;
                printf("%lld\n",sum);
        }
    }
    return 0;
}

 

posted @ 2017-07-17 09:38  夜雨声不烦  阅读(172)  评论(0编辑  收藏  举报