Cod sursa(job #1700985)

Utilizator xtreme77Patrick Sava xtreme77 Data 11 mai 2016 21:48:47
Problema Arbori de intervale Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 14.34 kb
/**
 * Code by Patrick Sava
 * "Spiru Haret" National College of Bucharest
 **/

# include "fstream"
# include "cstring"
# include "vector"
# include "queue"
# include "bitset"
# include "algorithm"
# include "map"
# include "set"
# include "unordered_map"
# include "deque"
# include "string"
# include "iomanip"
# include "cmath"
# include "stack"
# include "cassert"

const char IN [ ] =  "input" ;
const char OUT [ ] = "output" ;

using namespace std ;

# define pb push_back
# define mp make_pair
# define FORN( a , b , c ) for ( register int a = b ; a <= c ; ++ a )
# define FORNBACK( a , b , c ) for ( register int a = b ; a >= c ; -- a )

ifstream cin ( IN ) ;
ofstream cout ( OUT ) ;

const int MAX = 1e5 + 14 ;

class SegmentTree {

public :
    vector < long long > Sum ;
    vector < long long > Tree ;
    vector < long long > Lazy ;
    SegmentTree ( ) {
        Sum.resize ( MAX << 2 ) ;
        Tree.resize ( MAX << 2 ) ;
        Lazy.resize ( MAX << 2 ) ;
    }
    void Reset ( )
    {
        fill ( Sum.begin ( ) , Sum.end ( ) , 0 ) ;
        fill ( Tree.begin ( ) , Tree.end ( ) , 0 ) ;
        fill ( Lazy.begin ( ) , Lazy.end ( ) , 0 ) ;
    }
    void Push ( int nod , int st , int dr , int level )
    {
        if ( level == 2 ) {
            return ;
        }
        if ( Lazy [ nod ] ) {
            Tree [ nod ] += Lazy [ nod ] ;
            Sum [ nod ] += Lazy [ nod ] * ( dr - st + 1 ) ;
            if ( st != dr ) {
                Lazy [ nod << 1 ] += Lazy [ nod ] ;
                Lazy [ nod << 1 | 1 ] += Lazy [ nod ] ;
            }
            Lazy [ nod ] = 0 ;
            int mij = ( st + dr ) >> 1 ;
            if ( st != dr ) {
                Push ( nod << 1 , st , mij , level + 1 ) ;
                Push ( nod << 1 | 1 , mij + 1 , dr , level + 1 ) ;
            }
        }
    }
    long long Acces ( int nod , int st , int dr , int pos )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( st == dr ) {
            return Tree [ nod ] ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( pos <= mij ) {
            return Acces ( nod << 1 , st , mij , pos ) ;
        }
        else {
            return Acces ( nod << 1 | 1 , mij + 1 , dr , pos ) ;
        }
        Tree [ nod ] = Tree [ nod << 1 ] + Tree [ nod << 1 | 1 ] ;
        Sum [ nod ] = Sum [ nod << 1 ] + Sum [ nod << 1 | 1 ] ;
    }
    void ElementUpdate ( int nod , int st , int dr , int pos , int val )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( st == dr ) {
            Tree [ nod ] = val ;
            Sum [ nod ] = val ;
            return ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( pos <= mij ) {
            ElementUpdate ( nod << 1 , st , mij , pos , val ) ;
        }
        else {
            ElementUpdate ( nod << 1 | 1 , mij + 1 , dr , pos , val ) ;
        }
        Tree [ nod ] = max ( Tree [ nod << 1 ] , Tree [ nod << 1 | 1 ] ) ;
        Sum [ nod ] = Sum [ nod << 1 ] + Sum [ nod << 1 | 1 ] ;
    }
    void RangeUpdate ( int nod , int st , int dr , int a , int b , long long Value )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( a <= st and dr <= b ) {
            Lazy [ nod ] += Value ;
            return ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( a <= mij ) {
            RangeUpdate ( nod << 1 , st , mij , a , b , Value ) ;
        }
        if ( b > mij ) {
            RangeUpdate ( nod << 1 | 1 , mij + 1 , dr , a , b , Value ) ;
        }
        Tree [ nod ] = max ( Tree [ nod << 1 ] , Tree [ nod << 1 | 1 ] ) ;
        Sum [ nod ] = Sum [ nod << 1 ] + Sum [ nod << 1 | 1 ] ;
    }
    long long RangeQuery ( int nod , int st , int dr , int a , int b )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( a <= st and dr <= b ) {
            return Tree [ nod ] ;
        }
        int mij = ( st + dr ) >> 1 ;
        long long LeftMaximum = 0 ;
        long long RightMaximum = 0 ;
        if ( a <= mij ) {
            LeftMaximum = RangeQuery ( nod << 1 , st , mij , a , b ) ;
        }
        if ( b > mij ) {
            RightMaximum = RangeQuery ( nod << 1 | 1 , mij + 1 , dr , a , b ) ;
        }
        Tree [ nod ] = max ( Tree [ nod << 1 ] , Tree [ nod << 1 | 1 ] ) ;
        Sum [ nod ] = Sum [ nod << 1 ] + Sum [ nod << 1 | 1 ] ;
        return max ( LeftMaximum , RightMaximum ) ;
    }
    long long RangeSumQuery ( int nod , int st , int dr , int a , int b )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( a <= st and dr <= b ) {
            return Sum [ nod ] ;
        }
        int mij = ( st + dr ) >> 1 ;
        long long LeftSum = 0 ;
        long long RightSum = 0 ;
        if ( a <= mij ) {
            LeftSum = RangeSumQuery ( nod << 1 , st , mij , a , b ) ;
        }
        if ( b > mij ) {
            RightSum = RangeSumQuery ( nod << 1 | 1 , mij + 1 , dr , a , b ) ;
        }
        Tree [ nod ] = max ( Tree [ nod << 1 ] , Tree [ nod << 1 | 1 ] ) ;
        Sum [ nod ] = Sum [ nod << 1 ] + Sum [ nod << 1 | 1 ] ;
        return LeftSum + RightSum ;
    }

};

class PersistentSegmentTree
{
public :
    struct Tree {
        int leftt ;
        int rightt ;
        long long Sum ;
        long long Max ;
        long long Lazy ;
    };
    vector < int > Roots ;
    vector < Tree > Arb ;
    int nodes ;
    PersistentSegmentTree ( )
    {
        nodes = 0 ;
        Roots.resize ( MAX << 2 ) ;
        Arb.resize ( MAX << 2 ) ;
    }
    int copynode ( int nod )
    {
        ++ nodes ;
        Arb [ nodes ] = Arb [ nod ] ;
        return nodes ;
    }
    void resetP ( )
    {
        fill ( Roots.begin() , Roots.end() , 0 ) ;
        Arb.clear() ;
        nodes = 0 ;
    }
    void Push ( int nod , int st , int dr , int level )
    {
        if ( level == 2 ) {
            return ;
        }
        if ( Arb [ nod ].Lazy ) {
            Arb [ nod ].Max += Arb [ nod ].Lazy ;
            Arb [ nod ].Sum += Arb [ nod ].Lazy * ( dr - st + 1 ) ;
            if ( st != dr ) {
                int leftson = Arb [ nod ].leftt ;
                int rightson = Arb [ nod ].rightt ;
                Arb [ leftson ].Lazy += Arb [ nod ].Lazy ;
                Arb [ rightson ].Lazy += Arb [ nod ].Lazy ;
            }
            Arb [ nod ].Lazy = 0 ;
            int mij = ( st + dr ) >> 1 ;
            if ( st != dr ) {
                Push ( Arb [ nod ].leftt , st , mij , level + 1 ) ;
                Push ( Arb [ nod ].rightt , mij + 1 , dr , level + 1 ) ;
            }
        }
    }
    long long Acces ( int nod , int st , int dr , int pos )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( st == dr ) {
            return Arb [ nod ].Max ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( pos <= mij ) {
            return Acces ( Arb [ nod ].leftt , st , mij , pos ) ;
        }
        else {
            return Acces ( Arb [ nod ].rightt , mij + 1 , dr , pos ) ;
        }
        Arb [ nod ].Max = max ( Arb [ Arb [ nod ].leftt ].Max , Arb [ Arb [ nod ].rightt ].Max ) ;
        Arb [ nod ].Sum = Arb [ Arb [ nod ].leftt ].Sum + Arb [ Arb [ nod ].rightt ].Sum ;
    }
    int NewRootAfterUpdateonPosition ( int nod , int st , int dr , int pos , int val )
    {
        Push ( nod , st , dr , 0 ) ;
        nod = copynode ( nod ) ;
        if ( st == dr ) {
            Arb [ nod ].Max = val ;
            Arb [ nod ].Sum = val ;
            return nod ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( pos <= mij ) {
            Arb [ nod ].leftt = NewRootAfterUpdateonPosition ( Arb [ nod ].leftt , st , mij , pos , val ) ;
        }
        else {
            Arb [ nod ].rightt = NewRootAfterUpdateonPosition ( Arb [ nod ].rightt , mij + 1 , dr , pos , val ) ;
        }
        Arb [ nod ].Max = max ( Arb [ Arb [ nod ].leftt ].Max , Arb [ Arb [ nod ].rightt ].Max ) ;
        Arb [ nod ].Sum = Arb [ Arb [ nod ].leftt ].Sum + Arb [ Arb [ nod ].rightt ].Sum ;
        return nod ;
    }
    int RangeUpdate ( int nod , int st , int dr , int a , int b , long long Value )
    {
        Push ( nod , st , dr , 0 ) ;
        nod = copynode ( nod ) ;
        if ( a <= st and dr <= b ) {
            Arb [ nod ].Lazy += Value ;
            return nod ;
        }
        int mij = ( st + dr ) >> 1 ;
        if ( a <= mij ) {
            Arb [ nod ].leftt = RangeUpdate ( Arb [ nod ].leftt , st , mij , a , b , Value ) ;
        }
        if ( b > mij ) {
            Arb [ nod ].rightt = RangeUpdate ( Arb [ nod ].rightt , mij + 1 , dr , a , b , Value ) ;
        }
        Arb [ nod ].Max = max ( Arb [ Arb [ nod ].leftt ].Max , Arb [ Arb [ nod ].rightt ].Max ) ;
        Arb [ nod ].Sum = Arb [ Arb [ nod ].leftt ].Sum + Arb [ Arb [ nod ].rightt ].Sum ;
        return nod ;
    }
    long long SumonCurrentInterval ( int nod , int st , int dr , int a , int b )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( a <= st and dr <= b ) {
            return Arb [ nod ].Sum ;
        }
        int mij = ( st + dr ) >> 1 ;
        long long LeftSum = 0 ;
        long long RightSum = 0 ;
        if ( a <= mij ) {
            LeftSum = SumonCurrentInterval ( Arb [ nod ].leftt , st , mij , a , b ) ;
        }
        if ( b > mij ) {
            RightSum = SumonCurrentInterval ( Arb [ nod ].rightt , mij + 1 , dr , a , b ) ;
        }
        Arb [ nod ].Max = max ( Arb [ Arb [ nod ].leftt ].Max , Arb [ Arb [ nod ].rightt ].Max ) ;
        Arb [ nod ].Sum = Arb [ Arb [ nod ].leftt ].Sum + Arb [ Arb [ nod ].rightt ].Sum ;
        return LeftSum + RightSum ;
    }
    long long MaximumonCurrentInterval ( int nod , int st , int dr , int a , int b )
    {
        Push ( nod , st , dr , 0 ) ;
        if ( a <= st and dr <= b ) {
            return Arb [ nod ].Max ;
        }
        int mij = ( st + dr ) >> 1 ;
        long long LeftMaximum = 0 ;
        long long RightMaximum = 0 ;
        if ( a <= mij ) {
            LeftMaximum = MaximumonCurrentInterval ( Arb [ nod ].leftt , st , mij , a , b ) ;
        }
        if ( b > mij ) {
            RightMaximum = MaximumonCurrentInterval ( Arb [ nod ].rightt , mij + 1 , dr , a , b ) ;
        }
        Arb [ nod ].Max = max ( Arb [ Arb [ nod ].leftt ].Max , Arb [ Arb [ nod ].rightt ].Max ) ;
        Arb [ nod ].Sum = Arb [ Arb [ nod ].leftt ].Sum + Arb [ Arb [ nod ].rightt ].Sum ;
        return max ( LeftMaximum , RightMaximum ) ;
    }

};

int main ( void )
{
    int n , m ;
    cin >> n >> m ;
    SegmentTree Arbore ;
    Arbore.Reset() ;
    PersistentSegmentTree Copac ;
    Copac.resetP() ;
    FORN ( i , 1 , n ) {
        int Value ;
        cin >> Value ;
        Arbore.ElementUpdate ( 1 , 1 , n , i , Value ) ;
    }
    /***FORN ( i , 1 , n ) {
        cout << Arbore.Acces ( 1 , 1 , n , i ) << ' ' ;
    }
    cout << '\n' ;
    FORN ( len , 1 , n ) {
        cout << "sumele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " suma este " << Arbore.RangeSumQuery ( 1 , 1 , n , i , j ) << '\n' ;
        }
    }
    cout << '\n' ;
    FORN ( len , 1 , n ) {
        cout << "maximele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " maximul este " << Arbore.RangeQuery ( 1 , 1 , n , i , j ) << '\n' ;
        }
    }
    Arbore.RangeUpdate ( 1 , 1 , n , 1 , n , 1 ) ;
    //FORN ( i , 1 , n ) {
    //    cout << Arbore.Acces ( 1 , 1 , n , i ) << ' ' ;
    //}
    cout << '\n' ;
    FORNBACK ( len , n , 1 ) {
        cout << "sumele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " suma este " << Arbore.RangeSumQuery ( 1 , 1 , n , i , j ) << '\n' ;
        }
    }
    cout << '\n' ;
    FORNBACK ( len , n , 1 ) {
        cout << "maximele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " maximul este " << Arbore.RangeQuery ( 1 , 1 , n , i , j ) << '\n' ;
        }
    }
    return 0 ;***/
    while ( m -- ) {
        int Type ;
        cin >> Type ;
        if ( not Type ) {
            int _Left , _Right ;
            cin >> _Left >> _Right ;
            cout << Arbore.RangeQuery ( 1 , 1 , n , _Left , _Right ) << '\n' ;
        }
        else {
            int Position , Value ;
            cin >> Position >> Value ;
            Arbore.ElementUpdate ( 1 , 1 , n , Position , Value ) ;
        }
    }
    /***
    FORN ( i , 1 , n ) {
        int Value ;
        cin >> Value ;
        Copac.Roots [ i ] = Copac.NewRootAfterUpdateonPosition ( Copac.Roots [ i - 1 ] , 1 , n , i , Value ) ;
    }***/
    //FORN ( i , 1 , n ) {
    //    cout << Copac.Acces ( Copac.Roots [ n ] , 1 , n , i ) << ' ' ;
    //}
    //cout << '\n' ;
    //Copac.RangeUpdate ( Copac.Roots [ n ] , 1 , n , 1 , n , 1 ) ;
    //FORN ( i , 1 , n ) {
    //    cout << Copac.Acces ( Copac.Roots [ n ] , 1 , n , i ) << ' ' ;
    //}
    /*cout << '\n' ;
    FORNBACK ( len , n , 1 ) {
        cout << "sumele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " suma este " << Copac.SumonCurrentInterval( Copac.Roots [ n ] , 1 , n , i , j ) << '\n' ;
        }
    }
    cout << '\n' ;
    FORNBACK ( len , n , 1 ) {
        cout << "maximele pe intervalele de lungime " << len << " sunt \n" ;
        FORN ( i , 1 , n ) {
            int j = i + len - 1 ;
            if ( j > n ) {
                break ;
            }
            cout << "pe intervalul " << i << ' ' << j << " maximul este " << Copac.MaximumonCurrentInterval ( Copac.Roots [ n ] , 1 , n , i , j ) << '\n' ;
        }
    }*/
    return 0;
}