Cod sursa(job #755485)

Utilizator informatician28Andrei Dinu informatician28 Data 5 iunie 2012 21:51:24
Problema Datorii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <fstream>
#define DIM 524288
#define left(n) 2*(n)
#define right(n) (2*(n)+1)

using namespace std;

ifstream in("datorii.in");
ofstream out("datorii.out");

int N, M, V, Queryx, Queryy, T;
struct arbore
{
    int Upd, Sum;
}Tree[DIM];

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 (left(Node), Left, Middle, Left, Middle, Tree[Node].Upd); //imping informatia in fiul stang
    Update (right(Node), 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 curent7]
        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;
}

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;
}
int main()
{
    int i, X, indice;

    in >> N >> M;
    for(i = 1; i <= N; i++)
    {
        in >> X;
        Update(1,1,N,i,i,X);
    }
    for(i = 1; i <= M; i++)
    {
        in >> indice;
        if( indice == 0 )
        {
            in >> T >> V;
            Update(1,1,N,T,T,-V);
        }
        else
        {
            in >> Queryx >> Queryy;
            out << QuerySum(1,1,N,Queryx,Queryy) << '\n';
        }
    }
    return 0;
}