Cod sursa(job #1166640)

Utilizator andreiiiiPopa Andrei andreiiii Data 3 aprilie 2014 18:46:01
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.87 kb
#include <algorithm>
#include <cstdio>
#include <vector>
#include <bitset>

using namespace std;

const int N=100005;

class SegmentTree{
public:
    SegmentTree(const int _n=0, vector<int> _vals=vector<int>()):
        n(_n),
        aint(vector<int>(5*_n+2)),
        vals(_vals)
        {
            if(_n) Build(1, 1, n);
        }
    void update(const int poz, const int val)
    {
        X=poz;
        Y=val;
        Update(1, 1, n);
    }
    int query(const int st, const int dr)
    {
        ret=0;
        X=st;
        Y=dr;
        Query(1, 1, n);
        return ret;
    }
private:
    int n, X, Y, ret;
    vector<int> aint, vals;
    void Build(int nod, int l, int r)
    {
        if(l==r)
        {
            aint[nod]=vals[l];
            return;
        }
        int mid=(l+r)/2;
        Build(2*nod, l, mid);
        Build(2*nod+1, mid+1, r);
        aint[nod]=max(aint[2*nod], aint[2*nod+1]);
    }
    void Update(int nod, int l, int r)
    {
        if(l==r)
        {
            aint[nod]=Y;
            return;
        }
        int mid=(l+r)/2;
        if(X<=mid) Update(2*nod, l, mid);
        else Update(2*nod+1, mid+1, r);
        aint[nod]=max(aint[2*nod], aint[2*nod+1]);
    }
    void Query(int nod, int l, int r)
    {
        if(X<=l&&r<=Y)
        {
            if(aint[nod]>ret) ret=aint[nod];
            return;
        }
        int mid=(l+r)/2;
        if(X<=mid) Query(2*nod, l, mid);
        if(Y>mid) Query(2*nod+1, mid+1, r);
    }
};

int a[N], Lvl[N], f[N], nr[N], Path[N], Poz[N], Pathf[N];
int nrpaths;
vector<int> G[N], paths[N], values;
vector<SegmentTree> A;

void dfs1(const int n, const int fa)
{
    f[n]=fa;
    if(fa) G[n].erase(find(G[n].begin(), G[n].end(), fa));
    nr[n]=1;
    int nod=0;
    for(auto p: G[n])
    {
        dfs1(p, n);
        nr[n]+=nr[p];
        if(nr[p]>nr[nod]) nod=p;
    }
    if(!nod) Path[n]=++nrpaths;
    else Path[n]=Path[nod];
    paths[Path[n]].push_back(n);
}

void dfs2(const int n)
{
    for(auto p: G[n])
    {
        if(Path[p]!=Path[n])
        {
            Lvl[Path[p]]=Lvl[Path[n]]+1;
            Pathf[Path[p]]=n;
        }
        dfs2(p);
    }
}

int main()
{
    freopen("heavypath.in", "r", stdin);
    freopen("heavypath.out", "w", stdout);
    int n, q, i, j, x, y, sol=0, p;
    scanf("%d%d", &n, &q);
    for(i=1;i<=n;i++) scanf("%d", &a[i]);
    for(i=1;i<n;i++)
    {
        scanf("%d%d", &x, &y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    dfs1(1, 0);
    A=vector<SegmentTree>(nrpaths+1);
    for(i=1;i<=nrpaths;i++)
    {
        paths[i].push_back(0);
        reverse(paths[i].begin(), paths[i].end());
        for(vector<int>::iterator it=paths[i].begin();it!=paths[i].end();it++)
        {
            Poz[*it]=it-paths[i].begin();
            values.push_back(a[*it]);
        }
        paths[i].clear();
        A[i]=SegmentTree(values.size()-1, values);
        values.clear();
    }
    dfs2(1);
    while(q--)
    {
        scanf("%d%d%d", &i, &x, &y);
        if(!i)
        {
            A[Path[x]].update(Poz[x], y);
        }
        else
        {
            i=Path[x];
            j=Path[y];
            sol=0;
            while(i!=j)
            {
                if(Lvl[i]>Lvl[j])
                {
                    p=A[i].query(1, Poz[x]);
                    if(sol<p) sol=p;
                    x=Pathf[i];
                    i=Path[x];
                }
                else
                {
                    p=A[j].query(1, Poz[y]);
                    if(sol<p) sol=p;
                    y=Pathf[j];
                    j=Path[y];
                }
            }
            p=A[i].query(min(Poz[x], Poz[y]), max(Poz[x], Poz[y]));
            if(sol<p) sol=p;
            printf("%d\n", sol);
        }
    }
}