zoukankan      html  css  js  c++  java
  • 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
    ",sum);
            }
        }
        return 0;
    }

    如果运气好也是错,那我倒愿意错上加错!

    ❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀❀

  • 相关阅读:
    利用xslt合并多个xml文件到一个文件
    如果利用网络推广老家的特产水果?
    C#并行编程中的Parallel.Invoke
    Asp.Net MVC实现优酷(youku)Web的上传
    修改用户名后TSF出现"需要本地工作区。工作区 xxx 并未驻留在本计算机上"
    JS浏览器滚轮事件实现横向滚动照片展
    Android实现dialog时候弹出软键盘dialog移位问题
    快速搭建多线程Windows服务解决方案
    Difference between WCF and Web API and WCF REST and Web Service
    WPF应用程序的性能提升(一)
  • 原文地址:https://www.cnblogs.com/zxqxwnngztxx/p/7192860.html
Copyright © 2011-2022 走看看