Cod sursa(job #1135718)

Utilizator PatrikStepan Patrik Patrik Data 8 martie 2014 12:04:13
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 5.18 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] , Gp[NMAX];
    int tp[NMAX] , p[NMAX];
    bool u[NMAX];

    void read();
    void DFS(int nod);
    void write();
    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);
    int 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 = 1 ; i<= N ; ++i )
            for(int j = 0 ; j <(int)G[i].size() ; ++j )
            if(wp[i] != wp[G[i][j]])
            {
                Gp[wp[i]].pb(wp[G[i][j]]);
                Gp[wp[G[i][j]]].pb(wp[i]);
            }
        DFSp(wp[1]);
        for(int i = 1 ; i<= N ; ++i )
            for(int j = 0 ; j < (int)G[i].size() ; ++j )
                if(wp[i] != wp[G[i][j]] && niv[i] < niv[G[i][j]])tp[wp[G[i][j]]] = i;
        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
                printf("%d\n" , solve(x,y));
        }
        //write();
        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 maxx , fiu;
        d[nod] = 1;
        if(G[nod].size() == 1 && nod != 1)
        {
            path[++nrp].pb(nod);
            wp[nod] = nrp;
        }
        else
        {
            for(int i = 0 ; i < (int)G[nod].size() ; ++i)
            {
                if(G[nod][i] == t[nod])continue;
                maxx = 0;
                fiu = 0;
                t[G[nod][i]] = nod;
                niv[G[nod][i]] = niv[nod]+1;
                DFS(G[nod][i]);
                if(d[G[nod][i]] > maxx)
                {
                    maxx = d[G[nod][i]];
                    fiu = G[nod][i];
                }
            }
            path[wp[fiu]].pb(nod);
            wp[nod] = wp[fiu];
        }
    }

    void write()
    {
        freopen("heavypath.out" , "w" , stdout );
        for(int i = 1 ; i <= nrp ; ++i )
        {
            for(int j = 0 ; j < A[i].size() ; ++j )
                printf("%d " , A[i][j] );
            printf("\n");
        }
    }

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

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

    int solve(int x , int y)
    {
        int rez = 0 , aux;
        while(wp[x] != wp[y])
        {
            if(lev[wp[x]] < lev[wp[y]])
            {
                rez  = max(rez,query(wp[y],1,1,path[wp[y]].size()-1,1,p[y]));
                y = tp[wp[y]];
            }
            else
            {
                rez = max(rez,query(wp[x],1,1,path[wp[x]].size()-1,1,p[x]));
                x = tp[wp[x]];
            }
        }
        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]));
        return rez;
    }