Cod sursa(job #1252357)

Utilizator xtreme77Patrick Sava xtreme77 Data 30 octombrie 2014 17:59:16
Problema Arbore Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.47 kb
/*
 * Code by Spiromanul
 */

/*
 * Pasul 1:Liniarizam ( dar atunci cand liniarizam,retinem pozitia pe care apare primul nod $nod si pozitia pe care apare ultimul nod $nod
 * Pasul 2: Construim structul AINT cu campurile sum si maxim
 * PROOF : sum este cat s-a primit pe intervalul [ st , dr ]
 * PROOF : maxim este valoarea maxima primita de un nod din intervalul [ st , dr ]
 * Pasul 3 : bagam arbori de intervale si luam 100
 * Avantajul 1 : complexitate mai buna decat sqrt pe query ? da! log n pe query !
 * Avantajul 2 : Memorie mai putina ca la solutiile in sqrt
 * Avantajul 3 : Timp de executie mai mic
 */

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <cassert>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <utility>
#include <ctime>
#include <bitset>

#define pb push_back

const char IN [ ] = "arbore.in" ;
const char OUT [ ] = "arbore.out" ;
const int MAX = 100014 ;

using namespace std ;

ifstream fin ( IN ) ;
ofstream fout ( OUT ) ;

struct AINT {
    int sum , maxim ;
};

AINT arb [ MAX * 11 ] ;

vector < int > gr [ MAX ] ;

int stanga [ MAX ] , dreapta [ MAX ] , nr , lin [ ( MAX << 1 )+ 14 ] , sol ;

bitset < MAX > viz ;

void dfs ( int nod )
{
    viz [ nod ] = 1 ;
    lin [ ++ nr ] = nod ;
    stanga [ nod ] = nr ;
    for ( auto x : gr [ nod ] )
        if ( viz [ x ] == 0 )
            dfs ( x ) ;
    lin [ ++ nr ] = nod ;
    dreapta [ nod ] = nr ;
}

void update ( int nod , int st , int dr , int NODD , int add )
{
    if ( stanga [ NODD ] <= st and dr <= dreapta [ NODD ] )
    {
        arb [ nod ].sum += add ;
        arb [ nod ].maxim = arb [ nod ].sum + max ( arb [ nod << 1 ].maxim , arb [ nod << 1 | 1 ].maxim ) ;
        return ;
    }
    else {
        int mij = ( st + dr ) >> 1 ;
        if ( stanga [ NODD ] <= mij )
            update ( nod << 1 , st , mij , NODD , add ) ;
        if ( dreapta [ NODD ] > mij )
            update ( nod << 1 | 1 , mij + 1 , dr , NODD , add ) ;
        arb [ nod ].maxim = arb [ nod ].sum + max ( arb [ nod << 1 ].maxim , arb [ nod << 1 | 1 ].maxim ) ;
    }
}

void Query ( int nod , int st , int dr , int suma )
{
    if ( sol >= 1 )
        return ;
    if ( arb [ nod ].sum == suma )
    {
        sol = lin [ st ] ;
        return ;
    }
    if ( st < dr and arb [ nod ].sum < suma and arb [ nod ].maxim >= suma )
    {
        int mij = ( st + dr ) >> 1 ;
        Query ( nod << 1 , st , mij , suma - arb [ nod ].sum ) ;
        Query ( nod << 1 | 1 , mij + 1 , dr , suma - arb [ nod ].sum ) ;
    }

}

int main (              )
{
    int n , m ;
    fin >> n >> m ;
    for ( int i = 1 ; i < n ; ++ i )
    {
        int x , y ;
        fin >> x >> y ;
        gr [ x ].pb ( y ) ;
        gr [ y ].pb ( x ) ;
    }
    dfs ( 1 ) ;
    for ( ; m ; -- m )
    {
        int cod ;
        fin >> cod ;
        if ( cod == 1 )
            {
            int NODD , bag ;
            fin >> NODD >> bag ;
            //in loc sa bagam update pe n,bagam pe nr adica cardinalul reprezentarii euleriene
            update ( 1 , 1 , nr , NODD , bag ) ;
        }
        else {
            int sum ;
            fin >> sum ;
            sol = -1 ;
            //in loc sa bagam query pe n,bagam pe nr adica cardinalul reprezentarii euleriene
            Query ( 1 , 1 , nr , sum ) ;
            fout << sol << '\n' ;
        }
    }
    return 0 ;
}