Nu aveti permisiuni pentru a descarca fisierul grader_test1.in

Cod sursa(job #3258840)

Utilizator AntaresAntares Antares Data 23 noiembrie 2024 20:37:25
Problema Heavy Path Decomposition Scor 20
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.89 kb
#include <fstream>
#include <vector>
using namespace std;
ifstream fin ("heavypath.in");
ofstream fout ("heavypath.out");
int n,q,ch,pos,x,y,nr;
int node[100001],valx[100001],l[100001],cnt[100001],t[100001],niv[100001],heavy[100001],heavyhead[100001];
vector <int> v[100001];
struct seg_tree
{
    int v[400001];
    int val;
    int pos;
    int posl,posr;
    int sol;
    void build (int nod,int st,int dr)
    {
        if (st==dr)
            v[nod]=valx[node[st]];
        else
        {
            int mid=(st+dr)/2;
            build (2*nod,st,mid);
            build (2*nod+1,mid+1,dr);
            v[nod]=max (v[2*nod],v[2*nod+1]);
        }
    }
    void update (int nod,int st,int dr)
    {
        if (st==dr)
            v[nod]+=val;
        else
        {
            int mid=(st+dr)/2;
            if (pos<=mid)
                update (2*nod,st,mid);
            if (pos>mid)
                update (2*nod+1,mid+1,dr);
            v[nod]=max (v[2*nod],v[2*nod+1]);
        }
    }
    void query (int nod,int st,int dr)
    {
        if (st>=posl&&dr<=posr)
            sol=max (sol,v[nod]);
        else
        {
            int mid=(st+dr)/2;
            if (posl<=mid)
                query (2*nod,st,mid);
            if (posr>mid)
                query (2*nod+1,mid+1,dr);
        }
    }
    void prep_update (int cpos,int cval)
    {
        pos=cpos;
        val=cval;
        update (1,1,n);
    }
    int prep_query (int cposl,int cposr)
    {
        posl=cposl;
        posr=cposr;
        sol=0;
        query (1,1,n);
        return sol;
    }
};
seg_tree aint;
void dfs1 (int nod,int tt,int nivel)
{
    niv[nod]=nivel;
    t[nod]=tt;
    for (int i=0; i<v[nod].size (); i++)
    {
        int vecin=v[nod][i];
        if (vecin!=tt)
        {
            dfs1 (vecin,nod,nivel+1);
            if (cnt[vecin]>cnt[heavy[nod]])
                heavy[nod]=vecin;
            cnt[nod]+=cnt[vecin];
        }
    }
}
void dfs2 (int nod,int tt)
{
    l[nod]=++nr;
    node[nr]=nod;
    if (heavy[nod]!=0) ///punem mai intai lantul greu
    {
        heavyhead[heavy[nod]]=heavyhead[nod]; ///punem capatul lantului si la vecin
        dfs2 (heavy[nod],nod);
    }
    for (int i=0; i<v[nod].size (); i++)
    {
        int vecin=v[nod][i];
        if (vecin!=tt&&vecin!=heavy[nod])
        {
            dfs2 (vecin,nod);
            heavyhead[vecin]=vecin; ///se incheie un lant
        }
    }
    ///r[nod]=nr; -> capatul subarborelui in liniarizare
}
/**
heavy[nod]=fiul greu al nodului nod
heavyhead[nod]=capatul lantului greu ce trece prin nod
**/
int query (int x,int y)
{
    int sol=0;
    while (heavyhead[x]!=heavyhead[y])
    {
        ///urcam cu nodul ce are niv[capat] mai mare
        ///NU cu nodul ce are nivelul mai mare (poate fi pe lantul cu lca deja)
        if (niv[heavyhead[x]]>niv[heavyhead[y]])
        {
            sol=max (sol,aint.prep_query (l[heavyhead[x]],l[x]));
            x=t[heavyhead[x]];
        }
        else
        {
            sol=max (sol,aint.prep_query (l[heavyhead[y]],l[y]));
            y=t[heavyhead[y]];
        }
    }
    if (l[x]<=l[y])
        sol=max (sol,aint.prep_query (l[x],l[y]));
    else
        sol=max (sol,aint.prep_query (l[y],l[x]));
    return sol;
}
int main()
{
    fin>>n>>q;
    for (int i=1; i<=n; i++)
        fin>>valx[i];
    for (int i=1; i<n; i++)
    {
        fin>>x>>y;
        v[x].push_back (y);
        v[y].push_back (x);
    }
    dfs1 (1,0,1);
    dfs2 (1,0);
    heavyhead[1]=1;
    aint.build (1,1,n);
    while (q--)
    {
        fin>>ch;
        if (ch==0)
        {
            fin>>pos>>x;
            aint.prep_update (l[pos],x-valx[pos]);
            valx[pos]=x;
        }
        else
        {
            fin>>x>>y;
            fout<<query (x,y)<<"\n";
        }
    }
    return 0;
}