Cod sursa(job #1173843)

Utilizator maritimCristian Lambru maritim Data 20 aprilie 2014 22:32:40
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.35 kb
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;

ifstream f("heavypath.in");
ofstream g("heavypath.out");

typedef vector<int>::iterator it;

#define MaxN 100100
#define mid ((li+ls)>>1)
#define fs (poz<<1)
#define fd ((poz<<1)+1)
#define tata (poz>>1)

int N,M,acc;
int D[MaxN];
vector<int> A[MaxN];
vector<int> Path[MaxN];
int H[MaxN], G[MaxN];
int whatPath[MaxN], whatPoz[MaxN];
vector<int> AINT[MaxN];

void citire(void)
{
    int a,b;

    f >> N >> M;
    for(int i=1;i<=N;i++)
        f >> D[i];

    for(int i=1;i<N;i++)
    {
        f >> a >> b;
        A[a].push_back(b);
        A[b].push_back(a);
    }
}

inline void HPD(int nod)
{
    int maxG = 0, pozMaxG = -1;
    G[nod] = 1;

    for(it i=A[nod].begin();i<A[nod].end();i++)
        if(!H[*i])
        {
            H[*i] = H[nod] + 1;
            HPD(*i);
            G[nod] += G[*i];
            
            if(maxG < G[*i])
                maxG = G[*i],
                pozMaxG = *i;
        }

    if(pozMaxG == -1)
    {
        Path[++acc].push_back(0);
        Path[acc].push_back(nod);
        whatPath[nod] = acc;
        whatPoz[nod] = 1;
    }
    else
    {
        Path[whatPath[pozMaxG]].push_back(nod);
        whatPath[nod] = whatPath[pozMaxG];
        whatPoz[nod] = whatPoz[pozMaxG]+1;

        for(it i=A[nod].begin();i<A[nod].end();i++)
            if(H[nod] < H[*i] && pozMaxG != *i)
                Path[whatPath[*i]][0] = nod;
    }
}

inline void make(int path, int poz, int li, int ls)
{
    if(li == ls)
    {
        AINT[path][poz] = D[Path[path][li]];

        return ;
    }

    make(path, fs, li, mid);
    make(path, fd, mid+1, ls);

    AINT[path][poz] = max(AINT[path][fs], AINT[path][fd]);
}

inline void update(int path, int poz, int li, int ls, int rPoz, int val)
{
    if(li == ls)
    {
        AINT[path][poz] = val;

        return ;
    }

    if(rPoz <= mid)
        update(path, fs, li, mid, rPoz, val);
    else
        update(path, fd, mid+1, ls, rPoz, val);

    AINT[path][poz] = max(AINT[path][fs], AINT[path][fd]);
}

inline int query(int path, int poz, int li, int ls, int a, int b)
{
    int maxInt = 0;

    if(a <= li && ls <= b)
        return AINT[path][poz];

    if(a <= mid)
        maxInt = query(path, fs, li, mid, a, b);
    if(mid < b)
        maxInt = max(maxInt, query(path, fd, mid+1, ls, a, b));

    return maxInt;
}

void makeAINT(void)
{
    for(int i=1;i<=acc;i++)
    {
        AINT[i].reserve(5*Path[i].size());
        make(i,1,1,Path[i].size()-1);
    }
}

inline void swap(int &a, int &b)
{
    int aux = a;
    a = b;
    b = aux;
}

inline int specified_query(int x, int y)
{
    int maxSpec = 0;

    if(Path[whatPath[x]][0] > Path[whatPath[y]][0])
        swap(x,y);

    if(whatPath[x] == whatPath[y])
        return query(whatPath[x], 1, 1, Path[whatPath[x]].size()-1, 
            min(whatPoz[y], whatPoz[x]), max(whatPoz[x], whatPoz[y]));

    maxSpec = query(whatPath[y], 1, 1, Path[whatPath[y]].size()-1, whatPoz[y], Path[whatPath[y]].size()-1);
    y = Path[whatPath[y]][0];

    return max(maxSpec, specified_query(x,y));
}

int main(void)
{
    int op, x, y;

    citire();
    H[1] = 1;
    HPD(1);

    makeAINT();
    
    for(int i=1;i<=M;i++)
    {
        f >> op >> x >> y;
        if(!op)
            update(whatPath[x], 1, 1, Path[whatPath[x]].size()-1, whatPoz[x], y);
        else
            g << specified_query(x,y) << "\n";
    }
}