zoukankan      html  css  js  c++  java
  • 用指针写线段树(维护乘法)

    今天肖神给我讲课,讲了一个用指针写的线段树,写起来比数组复杂,但是貌似动态开点操作好像简单一些。之前我也写过用指针的数据结构,所以理解起来不是很难。

    题目描述
    
    如题,已知一个数列,你需要进行下面三种操作:
    
    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、240 mod 38=2

    直接写代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(int i = a;i <= n;i++)
    typedef long long ll;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(),c > '9' || c < '0')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(),c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op == 1)
            x = -x;
    }
    struct node
    {
        node *lch,*rch;
        int sum,mul,add;
        node()
        {
            lch = 0;
            rch = 0;
            mul = 1;
            add = 0;
        }
    }*root;
    int n,m,p,a[100010];
    void update(node *u)
    {
        u->sum = (u->lch->sum + u->rch->sum) % p;
    }
    void build(node *&u,int l,int r)
    {
        u = new node;
        if(l == r)
        {
            u->sum = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(u->lch,l,mid);
        build(u->rch,mid + 1,r);
        update(u);
    }
    void refresh(node *u,int l,int r,int mul,int add)
    {
        u->sum = (ll)u->sum * mul % p;
        u->sum = (u->sum + (ll)add * (r - l + 1)) % p;
        u->mul = (ll)u->mul * mul % p;
        u->add = ((ll)u->add * mul + add) % p;
    }
    void push_down(node *u,int l,int r)
    {
        if(u->mul != 1 || u->add != 0)
        {
            int mid = (l + r) >> 1;
            refresh(u->lch,l,mid,u->mul,u->add);
            refresh(u->rch,mid + 1,r,u->mul,u->add);
            u->mul = 1;
            u->add = 0;
        }
    }
    void modify(node *u,int l,int r,int ql,int qr,int mul,int add)
    {
        if(l == ql && r == qr)
        {
            refresh(u,l,r,mul,add);
            return;
        }
        push_down(u,l,r);
        int mid = (l + r) >> 1;
        if(qr <= mid)
        {
            modify(u->lch,l,mid,ql,qr,mul,add);
        }
        else if(ql > mid)
        {
            modify(u->rch,mid + 1,r,ql,qr,mul,add);
        }
        else
        {
            modify(u->lch,l,mid,ql,mid,mul,add);
            modify(u->rch,mid + 1,r,mid + 1,qr,mul,add);
        }
        update(u);
    }
    int query(node *u,int l,int r,int ql,int qr)
    {
        if(l == ql && r == qr)
        {
            return u->sum;
        }
        push_down(u,l,r);
        int mid = (l + r) >> 1;
        if(qr <= mid)
        {
            return query(u->lch,l,mid,ql,qr);
        }
        else if(ql > mid)
        {
            return query(u->rch,mid + 1,r,ql,qr);
        }
        else
        {
            return (query(u->lch,l,mid,ql,mid) + query(u->rch,mid + 1,r,mid + 1,qr)) % p;
        }
    }
    int main()
    {
        read(n);read(m);read(p);
        duke(i,1,n)
            read(a[i]);
        build(root,1,n);
        int op,l,x,r;
        while(m--)
        {
            read(op);read(l);read(r);
            if(op == 1)
            {
                read(x);
                modify(root,1,n,l,r,x,0);
            }
            else if(op == 2)
            {
                read(x);
                modify(root,1,n,l,r,1,x);
            }
            else
            {
                printf("%d
    ",query(root,1,n,l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/DukeLv/p/9427122.html
Copyright © 2011-2022 走看看