BZOJ 1798: [Ahoi2009]Seq 维护序列seq

二次联通门 : BZOJ 1798: [Ahoi2009]Seq 维护序列seq

/*
     BZOJ 1798: [Ahoi2009]Seq 维护序列seq
     
     线段树
     
     主要是标记的顺序下放问题。。。
     乱搞一下就好。。
     乱推一下式子就行 
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#define Max 100005

using namespace std;

void read (long long &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 (long long 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');
}

long long M, N, Mod;

struct Segment
{
    
    struct Segment_Tree
    {
        long long l;
        long long r;
        long long Sum;
        long long Mul_flag;
        long long Add_flag;
        bool flag;
        
    };
    
    Segment_Tree tree[Max << 3];
    Segment_Tree *res, *L, *R;
    
    
    void Build (long long l, long long r, long long now)
    {
        tree[now].l = l;
        tree[now].r = r;
        if (l == r)
        {
            read (tree[now].Sum);
            return ;
        }
        long long Mid = (l + r) >> 1;
        Build (l, Mid, now << 1);
        Build (Mid + 1, r, now << 1 | 1);
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    void Change_Add (long long l, long long r, long long now, long long 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;
            }
        }
        long long Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            Change_Add (l, r, now << 1, to);
        else if (l > Mid)
            Change_Add (l, r, now << 1 | 1, to);
        else
        {
            Change_Add (l, Mid, now << 1, to);
            Change_Add (Mid + 1, r, now << 1 | 1, to);    
        }
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    void Change_Multiply (long long l, long long r, long long now, long long 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;
            }
        }
        long long Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            Change_Multiply (l, r, now << 1, to);
        else if (l > Mid)
            Change_Multiply (l, r, now << 1 | 1, to);
        else
        {
            Change_Multiply (l, Mid, now << 1, to);
            Change_Multiply (Mid + 1, r, now << 1 | 1, to);    
        }
        tree[now].Sum = (tree[now << 1].Sum + tree[now << 1 | 1].Sum) % Mod;
    }
    
    long long Query_sum (long long l, long long r, long long 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;
        long long Mid = (tree[now].l + tree[now].r) >> 1;
        if (r <= Mid)
            return Query_sum (l, r, now << 1) % Mod;
        else if (l > Mid)
            return Query_sum (l, r, now << 1 | 1) % Mod;
        else
            return (Query_sum (l, Mid, now << 1) + Query_sum (Mid + 1, r, now << 1 | 1)) % Mod; 
    }
};

Segment Tree;

int main (int argc, char *argv[])
{
    read (N);
    read (Mod);
    Tree.Build (1, N, 1);
    long long type;
    long long l, r, z;
    read (M);
    for (int i = 1; i <= M; i++)
    {
        read (type);
        read (l);
        read (r);
        switch (type)
        {
            case 1:
            {
                read (z);
                Tree.Change_Multiply (l, r, 1, z);
                break;
            }
            case 2:
            {
                read (z);
                Tree.Change_Add (l, r, 1, z);
                break;
            }
            case 3:
            {
                write (Tree.Query_sum (l, r, 1));
                putchar ('
');
                break;
            }
        }
    }    
    return 0;
}
原文地址:https://www.cnblogs.com/ZlycerQan/p/6749371.html