Cod sursa(job #1180513)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 30 aprilie 2014 18:37:26
Problema Arbori de intervale Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 5.2 kb
#include <iostream>
#include <fstream>

using namespace std;

template <class T>
class Parser
{
    public:

        Parser()
        {
            buffer = new char[BUFFER_SIZE];
            position = BUFFER_SIZE;
        }

        T getNumber( istream &f )
        {
            return getNr( f );
        }

        private:


            static const int BUFFER_SIZE = ( 1 << 14 );
            int position;

            char *buffer;

            char getChar( istream &f )
            {
                if ( position == BUFFER_SIZE )
                {
                    f.read( buffer, BUFFER_SIZE );
                    position = 0;
                }

                return buffer[ position++ ];
            }

            T getNr( istream &f )
            {
                T nr = (T)0;
                T sgn = (T)1;
                char ch;

                do
                {
                    ch = getChar( f );

                    if ( ch == '-' ) break;

                } while ( !isdigit( ch ) );

                if ( ch == '-' )
                {
                    sgn = (T)-1;
                    ch = getChar( f );
                }

                do
                {
                    nr = nr * (T)10 + ( ch - '0' );
                    ch = getChar( f );

                    if ( ch == '.' ) break;

                } while ( isdigit( ch ) );

                T pw10 = (T)10;

                if ( ch == '.' )
                {
                    ch = getChar( f );

                    do
                    {
                        nr = ( nr * pw10 + ( ch - '0' ) ) / pw10;
                        pw10 *= (T)10;
                        ch = getChar( f );

                    } while( isdigit( ch ) );
                }

                return ( nr * sgn );
            }
};

template <class T, T(*F)(T,T)>
class SQRTD
{
    const int INF = 1e9;

    public:

        SQRTD(){ }

        SQRTD( const int n, T a[] )
        {
            alloc_memory( n, a );
        }

        void alloc_memory( const int n, T a[] )
        {
            N = n;
            v = new T[N + 2];
            belong = new int[N + 2];

            for ( int i = 1; i <= N; ++i )
            {
                v[i] = a[i];
                belong[i] = 0;
            }

            SQRT = 1;

            while ( SQRT * SQRT < N ) SQRT++;

            d = new T[SQRT + 2];
            st = new int[SQRT + 2];
            dr = new int[SQRT + 2];

            for ( int i = 1; i <= SQRT; ++i )
            {
                d[i] = -INF;
                st[i] = INF;
                dr[i] = 0;
            }

            for ( int i = 1, x = 0; i <= N; ++i )
            {
                if ( i % SQRT == 1 ) x++;

                belong[i] = x;
            }

            for ( int i = 1, x = 0; i <= N; ++i )
            {
                if ( i % SQRT == 1 ) x++;

                st[x] = min( st[x], i );
                dr[x] = max( dr[x], min( st[x] + SQRT - 1, N ) );
            }

            init_decomposition();
        }

        T combine( T a, T b )
        {
            if ( a == -INF ) a = b;
            else             a = F( a, b );

            return a;
        }

        void init_decomposition()
        {
            for ( int i = 1; i <= N; ++i )
            {
                d[ belong[i] ] = combine( d[ belong[i] ], v[i] );
            }
        }

        void update( int pos, T new_val )
        {
            v[pos] = new_val;

            int apart = belong[pos];

            d[apart] = -INF;

            for ( int x = st[apart]; x <= dr[apart]; ++x )
            {
                d[apart] = combine( d[apart], v[x] );
            }
        }

        T query( int x, int y )
        {
            int apart_x = belong[x];
            int apart_y = belong[y];

            T sol = -INF;

            for ( int k = max( st[apart_x], x ); k <= min( dr[apart_x], y ); ++k )
            {
                if ( sol == -INF ) sol = v[k];
                else               sol = F( sol, v[k] );
            }

            for ( int k = apart_x + 1; k <= apart_y - 1; ++k )
            {
                if ( sol == -INF ) sol = d[k];
                else               sol = F( sol, d[k] );
            }

            if ( apart_x != apart_y )
            {
                for ( int k = st[apart_y]; k <= min( dr[apart_y], y ); ++k )
                {
                    if ( sol == -INF ) sol = v[k];
                    else               sol = F( sol, v[k] );
                }
            }

            return sol;
        }

    private:

        T *v, *d;
        int *belong, *st, *dr;
        int N, SQRT;
};

int maxim( int a, int b )
{
    return max( a, b );
}

int a[100000 + 5];
int N, M;

int main()
{
    ifstream f("arbint.in");
    ofstream g("arbint.out");

    Parser <int> P;

    N = P.getNumber( f );
    M = P.getNumber( f );

    for ( int i = 1; i <= N; ++i )
            a[i] = P.getNumber( f );

    SQRTD <int, maxim> R( N, a );

    for ( int i = 1, a, b, c; i <= M; ++i )
    {
        a = P.getNumber( f );
        b = P.getNumber( f );
        c = P.getNumber( f );

        if ( a == 0 )
        {
            g << R.query( b, c ) << "\n";
        }
        else
        {
            R.update( b, c );
        }
    }

    return 0;
}