zoukankan      html  css  js  c++  java
  • 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<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N=1e5+5;
    
    int p;
    long long a[N];
    struct Tree
    {
        int l,r,mid;
        long long v,mul,add;
    }tree[N<<2];
    
    void build(int root,int l,int r)
    {
        tree[root].l=l,tree[root].r=r,tree[root].mid=l+r>>1,tree[root].mul=1;
        if(l==r)
        {
            tree[root].v=a[l];
            return;
        }
        build(root<<1,l,tree[root].mid);
        build(root<<1|1,tree[root].mid+1,r);
        tree[root].v=tree[root<<1].v+tree[root<<1|1].v;
        tree[root].v%=p;
        return;
    }
    
    void push_down(int root)
    {
        tree[root<<1].v=(tree[root<<1].v*tree[root].mul+tree[root].add*(tree[root].mid-tree[root].l+1))%p;
        tree[root<<1|1].v=(tree[root<<1|1].v*tree[root].mul+tree[root].add*(tree[root].r-tree[root].mid))%p;
        tree[root<<1].mul=(tree[root<<1].mul*tree[root].mul)%p;
        tree[root<<1|1].mul=(tree[root<<1|1].mul*tree[root].mul)%p;
        tree[root<<1].add=(tree[root<<1].add*tree[root].mul+tree[root].add)%p;
        tree[root<<1|1].add=(tree[root<<1|1].add*tree[root].mul+tree[root].add)%p;
        tree[root].add=0;
        tree[root].mul=1;
        return;
    }
    
    void update1(int root,int l,int r,long long k)
    {
        if(r<tree[root].l||tree[root].r<l)
            return;
        if(l<=tree[root].l&&tree[root].r<=r)
        {
            tree[root].v=(tree[root].v*k)%p;
            tree[root].mul=(tree[root].mul*k)%p;
            tree[root].add=(tree[root].add*k)%p;
            return;
        }
        push_down(root);
        update1(root<<1,l,r,k);
        update1(root<<1|1,l,r,k);
        tree[root].v=(tree[root<<1].v+tree[root<<1|1].v)%p;
        return;
    }
    
    void update2(int root,int l,int r,long long k)
    {
        if(r<tree[root].l||tree[root].r<l)
            return;
        if(l<=tree[root].l&&tree[root].r<=r)
        {
            tree[root].add=(tree[root].add+k)%p;
            tree[root].v=(tree[root].v+k*(tree[root].r-tree[root].l+1))%p;
            return;
        }
        push_down(root);
        update2(root<<1,l,r,k);
        update2(root<<1|1,l,r,k);
        tree[root].v=(tree[root<<1].v+tree[root<<1|1].v)%p;
        return;
    }
    
    long long query(int root,int l,int r)
    {
        if(r<tree[root].l||tree[root].r<l)
            return 0;
        if(l<=tree[root].l&&tree[root].r<=r)
            return tree[root].v;
        push_down(root);
        return (query(root<<1,l,r)+query(root<<1|1,l,r))%p;
    }
    
    int main()
    {
        int n,m;
        scanf("%d%d%d",&n,&m,&p);
        for(int i=1;i<=n;++i)
            scanf("%lld",&a[i]);
        build(1,1,n);
        int type;
        int l,r;
        long long k;
        while(m--)
        {
            scanf("%d",&type);
            if(type==1)
            {
                scanf("%d%d%lld",&l,&r,&k);
                update1(1,l,r,k);
            }
            else if(type==2)
            {
                scanf("%d%d%lld",&l,&r,&k);
                update2(1,l,r,k);
            }
            else
            {
                scanf("%d%d",&l,&r);
                printf("%lld
    ",query(1,l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    iOS:网络检测
    WinJS:设置listView垂直滚动
    iOS:在AppDelegate中定义managed object context
    简笔画项目总结: ios绘图机制 & 实现记录笔迹功能
    CSS基础
    DOM小结
    iOS:view.frame
    WP:初探
    iOS:UIWebView scrollView 的分页滑动问题
    Mono for Android: 利用mono for android开发的第一个程序
  • 原文地址:https://www.cnblogs.com/lovewhy/p/9633502.html
Copyright © 2011-2022 走看看