Cod sursa(job #749070)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 15 mai 2012 18:37:51
Problema Datorii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.58 kb
#include <cstdio>
#include <algorithm>

#define Infinity 2000000000
#define NMax 500000

using namespace std;

struct TreeNode
{
    int Upd, Max, Sum;
};

TreeNode Tree[NMax];
int N;

inline void Update (int, int, int, int, int, int);
inline void PushDown (int, int, int);

inline void PushDown (int Node, int Left, int Right)
{
    int Middle=(Left+Right)/2;

    if (Tree[Node].Upd==0)
    {
        return; //nu am ce informatie sa imping in jos
    }

    Update (2*Node, Left, Middle, Left, Middle, Tree[Node].Upd); //imping informatia in fiul stang
    Update (2*Node+1, Middle+1, Right, Middle+1, Right, Tree[Node].Upd); //imping informatia in fiul drept
    Tree[Node].Upd=0; //sterg informatia din nodul curent
}

inline void Update (int Node, int Left, int Right, int UpdateLeft, int UpdateRight, int Val)
{
    int Middle=(Left+Right)/2;

    if (UpdateLeft<=Left and Right<=UpdateRight)
    {
        Tree[Node].Upd+=Val; //cresc valoarea adaugata la elementele din intervalul curent
        Tree[Node].Max+=Val; //cresc si valoarea minimului din intervalul curent
        Tree[Node].Sum+=(Val*(Right-Left+1)); //actualizez suma pe intervalul curent
        return;
    }

    PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce

    if (UpdateLeft<=Middle)
    {
        Update (2*Node, Left, Middle, UpdateLeft, UpdateRight, Val); //actualizez fiul stang
    }
    if (UpdateRight>Middle)
    {
        Update (2*Node+1, Middle+1, Right, UpdateLeft, UpdateRight, Val); //actualizez fiul drept
    }
    Tree[Node].Sum=Tree[2*Node].Sum+Tree[2*Node+1].Sum;
    Tree[Node].Max=max (Tree[Node].Max, Tree[Node].Max);
}

inline int QuerySum (int Node, int Left, int Right, int QueryLeft, int QueryRight)
{
    int Middle=(Left+Right)/2;

    if (QueryLeft<=Left and Right<=QueryRight)
    {
        return Tree[Node].Sum; //intervalul curent e cuprins in totalitate in intervalul pe care fac query
    }

    PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce

    int NodeSum=0;
    if (QueryLeft<=Middle)
    {
        NodeSum+=QuerySum (2*Node, Left, Middle, QueryLeft, QueryRight);
    }
    if (QueryRight>Middle)
    {
        NodeSum+=QuerySum (2*Node+1, Middle+1, Right, QueryLeft, QueryRight);
    }
    return NodeSum;
}

inline int QueryMax (int Node, int Left, int Right, int QueryLeft, int QueryRight)
{
    int Middle=(Left+Right)/2;

    if (QueryLeft<=Left and Right<=QueryRight)
    {
        return Tree[Node].Max; //intervalul curent e cuprins in totalitate in intervalul pe care fac query
    }

    PushDown (Node, Left, Right); //imping informatia din nodul curent in jos ca sa nu ma incurce

    int NodeMax=-Infinity;
    if (QueryLeft<=Middle)
    {
        NodeMax=max (NodeMax, QueryMax (2*Node, Left, Middle, QueryLeft, QueryRight));
    }
    if (QueryRight>Middle)
    {
        NodeMax=max (NodeMax, QueryMax (2*Node+1, Middle+1, Right, QueryLeft, QueryRight));
    }
    return NodeMax;
}

int main ()
{
    freopen ("datorii.in", "r", stdin);
    freopen ("datorii.out", "w", stdout);
    int NQ; scanf ("%d %d", &N, &NQ);
    for (int i=1; i<=N; ++i)
    {
        int X; scanf ("%d", &X);
        Update (1, 1, N, i, i, X);
    }
    for (; NQ>0; --NQ)
    {
        int Type, X, Y; scanf ("%d %d %d", &Type, &X, &Y);
        if (Type==0)
        {
            Update (1, 1, N, X, X, -Y);
        }
        else
        {
            printf ("%d\n", QuerySum (1, 1, N, X, Y));
        }
    }
    return 0;
}