zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    HTTP和SOAP完全就是两个不同的协议
    RabbitMQ七:交换机类型Exchange Types--Fanout 介绍
    日志级别简述
    RabbitMQ六:通过routingkey模拟日志
    http协议无状态中的 "状态" 到底指的是什么?!
    MySQL-时间(time、date、datetime、timestamp和year)
    API系列一:REST和RESTful认识
    Ref 和 Out 区别(演练代码)
    RabbitMQ五:生产者--队列--多消费者
    RabbitMQ四:生产者--队列--消费者
  • 原文地址:https://www.cnblogs.com/ZlycerQan/p/6805338.html
Copyright © 2011-2022 走看看