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;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/6805338.html