• luogu P3373 【模板】线段树 2


     二次联通门 : luogu P3373 【模板】线段树 2

    /*
         P3373 线段树 2
    
        
        此题的难点(雾)在于标记下放的顺序
        
        问题主要是没法分断是先乘还是先加
    
        一般的解决方法是把乘法变成加法。
    
        1:s*lazy+flag.
    
        2:(s+flag)*lazy=s*lazy+flag*lazy.
    
    */
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #define Max 100005
    
    using namespace std;
    
    typedef long long LL;
    
    void read (LL &now)
    {
        now = 0;
        char word = getchar ();
        bool temp = false;
        while (word < '0' || word > '9')
        {
            if (word == '-')
                temp = true;
            word = getchar ();
        }
        while (word >= '0' && word <= '9')
        {
            now = now * 10 + word - '0';
            word = getchar ();
        }
        if (temp)
            now = -now;
    }
    
    void write (LL now)
    {
        char word[20];
        int Len = 0;
        if (now == 0)
            putchar ('0');
        if (now < 0)
        {
            putchar ('-');
            now = -now;
        }
        while (now)
        {
            word[++Len] = now % 10;
            now /= 10;
        }
        while (Len--)
            putchar (word[Len + 1] + '0');
    }
    
    struct Tree
    {
        LL l;
        LL r;
        LL Sum;
        LL Mul_flag;
        LL Add_flag;
        bool flag;
        
    }tree[Max << 2];
    
    LL M, N, Mod;
    Tree *res, *L, *R;
    
    
    void Tree_Build (LL l, LL r, LL now)
    {
        tree[now].l = l;
        tree[now].r = r;
        if (l == r)
        {
            scanf ("%lld", &tree[now].Sum);
            return ;
        }
        LL Mid = (l + r) >> 1;
        Tree_Build (l, Mid, now << 1);
        Tree_Build (Mid + 1, r, now << 1 | 1);
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    void Tree_Add (LL l, LL r, LL now, LL to)
    {
        if (tree[now].l == l && tree[now].r == r)
        {
            tree[now].Add_flag = (tree[now].Add_flag + to) % Mod;
            tree[now].Sum = (tree[now].Sum + ((r - l + 1) * to)) % Mod;
            return ;
        }
        if (tree[now].Add_flag || tree[now].flag)
        {
            res = &tree[now];
            L = &tree[now << 1];
            R = &tree[now << 1 | 1];
            if (res->flag)
            {
                L->Sum = (L->Sum * res->Mul_flag) % Mod;
                R->Sum = (R->Sum * res->Mul_flag) % Mod;
                L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod;
                R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod;
                if (L->flag)
                    L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    L->Mul_flag = res->Mul_flag;
                    L->flag = true;
                }
                if (R->flag)
                    R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    R->Mul_flag = res->Mul_flag;
                    R->flag = true;
                }
                res->flag = false;
            }
            if (res->Add_flag)
            {
                L->Add_flag = (L->Add_flag + res->Add_flag) % Mod;
                R->Add_flag = (R->Add_flag + res->Add_flag) % Mod;
                L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod;
                R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod;
                res->Add_flag = 0;
            }
        }
        LL Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            Tree_Add (l, r, now << 1, to);
        else if (l > Mid)
            Tree_Add (l, r, now << 1 | 1, to);
        else
        {
            Tree_Add (l, Mid, now << 1, to);
            Tree_Add (Mid + 1, r, now << 1 | 1, to);    
        }
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    void Tree_Mul (LL l, LL r, LL now, LL to)
    {
        if (tree[now].l == l && tree[now].r == r)
        {
            tree[now].Sum = (tree[now].Sum * to) % Mod;
            tree[now].Add_flag = (tree[now].Add_flag * to) % Mod;
            if (tree[now].flag)
                tree[now].Mul_flag = (tree[now].Mul_flag * to) % Mod;
            else
            {
                tree[now].flag = true;
                tree[now].Mul_flag = to;
            }
            return ;
        }
        if (tree[now].Add_flag || tree[now].flag)
        {
            res = &tree[now];
            L = &tree[now << 1];
            R = &tree[now << 1 | 1];
            if (res->flag)
            {
                L->Sum = (L->Sum * res->Mul_flag) % Mod;
                R->Sum = (R->Sum * res->Mul_flag) % Mod;
                L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod;
                R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod;
                if (L->flag)
                    L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    L->Mul_flag = res->Mul_flag;
                    L->flag = true;
                }
                if (R->flag)
                    R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    R->Mul_flag = res->Mul_flag;
                    R->flag = true;
                }
                res->flag = false;
            }
            if (res->Add_flag)
            {
                L->Add_flag = (L->Add_flag + res->Add_flag) % Mod;
                R->Add_flag = (R->Add_flag + res->Add_flag) % Mod;
                L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod;
                R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod;
                res->Add_flag = 0;
            }
        }
        LL Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            Tree_Mul (l, r, now << 1, to);
        else if (l > Mid)
            Tree_Mul (l, r, now << 1 | 1, to);
        else
        {
            Tree_Mul (l, Mid, now << 1, to);
            Tree_Mul (Mid + 1, r, now << 1 | 1, to);    
        }
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    LL Tree_Query (LL l, LL r, LL now)
    {
        if (tree[now].l == l && tree[now].r == r)
            return tree[now].Sum % Mod;
            if (tree[now].Add_flag || tree[now].flag)
        {
            res = &tree[now];
            L = &tree[now << 1];
            R = &tree[now << 1 | 1];
            if (res->flag)
            {
                L->Sum = (L->Sum * res->Mul_flag) % Mod;
                R->Sum = (R->Sum * res->Mul_flag) % Mod;
                L->Add_flag = (L->Add_flag * res->Mul_flag) % Mod;
                R->Add_flag = (R->Add_flag * res->Mul_flag) % Mod;
                if (L->flag)
                    L->Mul_flag = (L->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    L->Mul_flag = res->Mul_flag;
                    L->flag = true;
                }
                if (R->flag)
                    R->Mul_flag = (R->Mul_flag * res->Mul_flag) % Mod;
                else
                {
                    R->Mul_flag = res->Mul_flag;
                    R->flag = true;
                }
                res->flag = false;
            }
            if (res->Add_flag)
            {
                L->Add_flag = (L->Add_flag + res->Add_flag) % Mod;
                R->Add_flag = (R->Add_flag + res->Add_flag) % Mod;
                L->Sum = (L->Sum + ((L->r - L->l + 1) % Mod) * res->Add_flag) % Mod;
                R->Sum = (R->Sum + ((R->r - R->l + 1) % Mod) * res->Add_flag) % Mod;
                res->Add_flag = 0;
            }
        }
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
        LL Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            return Tree_Query (l, r, now << 1) % Mod;
        else if (l > Mid)
            return Tree_Query (l, r, now << 1 | 1) % Mod;
        else
            return (Tree_Query (l, Mid, now << 1) + Tree_Query (Mid + 1, r, now << 1 | 1)) % Mod; 
    }
    
    int main (int argc, char *argv[])
    {
        read (N);
        read (M);
        read (Mod);
        Tree_Build (1, N, 1);
        LL type;
        LL l, r, z;
        for (int i = 1; i <= M; i++)
        {
            read (type);
            read (l);
            read (r);
            switch (type)
            {
                case 1:
                {
                    read (z);
                    Tree_Mul (l, r, 1, z);
                    break;
                }
                case 2:
                {
                    read (z);
                    Tree_Add (l, r, 1, z);
                    break;
                }
                case 3:
                {
                    write (Tree_Query (l, r, 1));
                    putchar ('
    ');
                    break;
                }
            }
        }    
        return 0;
    }
  • 相关阅读:
    图解JQUERY尺寸及位置定义
    JS中offsetTop、clientTop、scrollTop、offsetTop各属性介绍
    js拖拽的封装
    Git详解之九:Git内部原理
    Git详解之八:Git与其他系统
    量化投资的Python库——Tushare
    Python数据分析-Day2-Pandas模块
    Python数据分析-Day1-Numpy模块
    Python全栈开发-Day8-Socket网络编程
    Python全栈开发-Day7-面向对象编程2
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6805338.html
Copyright © 2020-2023  润新知