Cod sursa(job #1135804)

Utilizator PatrikStepan Patrik Patrik Data 8 martie 2014 13:56:46
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.17 kb
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    #define NMAX 100001
    #define pb push_back
    int N , M , d[NMAX] , t[NMAX] , nrp , wp[NMAX] , v[NMAX] ,niv[NMAX] , lev[NMAX] ;
    vector<int> G[NMAX] , path[NMAX] , A[NMAX];
    int tp[NMAX] , p[NMAX];
    bool u[NMAX];

    void read();
    void DFS(int nod);
    void build(int path , int n , int  l , int r);
    void update(int path , int n , int l , int r , int poz , int nod);
    int query(int path , int n , int l , int r , int a , int b);
    void solve(int x , int y);
    void DFSp(int nod);

    int main()
    {
        int tip, x , y;
        read();
        DFS(1);
        for(int i = 1 ; i <= nrp ; ++i )
        {
            path[i].pb(0);
            reverse(path[i].begin(),path[i].end());
            A[i].resize(path[i].size()*4);
            build(i,1,1,path[i].size()-1);
            for(int j = 1 ; j <(int)path[i].size() ; ++j )
                p[path[i][j]] = j;
        }
        for(int i = 2 ; i<= N ; ++i )
            if(wp[i] != wp[t[i]])tp[wp[i]] = t[i];
        DFSp(1);
        for(int i = 1 ; i<= M; ++i )
        {
            scanf("%d%d%d" , &tip , &x , &y );
            if(!tip)
            {
                v[x] = y;
                update(wp[x],1,1,path[wp[x]].size()-1,p[x],x);
            }
            else
                solve(x,y);
        }
        return 0;
    }

    void read()
    {
        int x , y;
        freopen("heavypath.in" , "r" , stdin );
        freopen("heavypath.out" , "w" , stdout );
        scanf("%d%d" , &N , &M  );
        for(int i = 1 ; i <= N ; ++i )
            scanf("%d" , &v[i]);
        for(int i = 1 ; i < N ; ++i )
        {
            scanf("%d%d" , &x , &y );
            G[x].pb(y);
            G[y].pb(x);
        }
    }

    void DFS(int nod)
    {
        int fiu = -1;
        d[nod] = 1;
            for(int i = 0 ; i < (int)G[nod].size() ; ++i)
            {
                if(G[nod][i] == t[nod])continue;
                t[G[nod][i]] = nod;
                niv[G[nod][i]] = niv[nod]+1;
                DFS(G[nod][i]);
                d[nod] += d[G[nod][i]];
                if(fiu == -1 || d[G[nod][i]] > d[fiu])
                    fiu = G[nod][i];
            }
        if(fiu == -1)wp[nod] = ++nrp;
        else wp[nod] = wp[fiu];
        path[wp[nod]].pb(nod);
    }

    void build(int i , int  n , int l , int r )
    {
        if(l == r)A[i][n] = v[path[i][l]];
        else
        {
            int m = (l+r)/2;
            build(i,2*n,l,m);
            build(i,2*n+1,m+1,r);
            A[i][n] = max(A[i][2*n] , A[i][2*n+1]);
        }
    }

    void update(int path , int  n , int  l , int r , int poz , int nod )
    {
        if( l == r )A[path][n] = v[nod];
        else
        {
            int m = (l+r)/2;
            if(poz <= m)update(path,2*n,l,m,poz,nod);
            else update(path,2*n+1,m+1,r,poz,nod);
            A[path][n] = max(A[path][2*n] , A[path][2*n+1]);
        }
    }

    int query(int i , int  n , int  l , int r , int a , int b)
    {
        if(a <= l && b >= r)return A[i][n];
        else
        {
            int m = (l+r)/2,maxx = -1;
            if(a <= m)
                maxx = query(i,2*n,l,m,a,b);
            if(b > m)
                maxx = max(maxx, query(i , 2*n+1,m+1,r,a,b));
            return maxx;
        }
    }

    void DFSp(int nod)
    {
        u[nod] = 1;
        for(int i = 0 ; i <(int)G[nod].size() ; ++i )
        {
            if(u[G[nod][i]])continue;
            if(wp[nod] != wp[G[nod][i]]) lev[wp[G[nod][i]]] = lev[wp[nod]] + 1;
            DFSp(G[nod][i]);
        }
    }

    void solve(int x , int y)
    {
        int aux, rez = 0;
        while(wp[x] != wp[y])
        {
            if(lev[wp[x]] > lev[wp[y]]){aux = x;x = y;y = aux;}
            rez = max(rez,query(wp[y],1,1,path[wp[y]].size()-1,1,p[y]));
            y = tp[wp[y]];
        }
        if(niv[x] > niv[y]){aux = x;x = y;y = aux;}
            rez = max(rez,query(wp[x],1,1,path[wp[x]].size()-1,p[x],p[y]));
        printf("%d\n" , rez);
    }