Cod sursa(job #1135690)

Utilizator Andrei1998Andrei Constantinescu Andrei1998 Data 8 martie 2014 11:26:54
Problema Heavy Path Decomposition Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.36 kb
#include <fstream>
#include <algorithm>
#include <vector>

using namespace std;

#define NMAX 100005

vector<int> graf[NMAX];
int gsize[NMAX];
int deph[NMAX];
int v[NMAX];

int what_path[NMAX];
int what_poz[NMAX];

struct path
{
    int father;
    vector<int> noduri;
};

struct elem
{
    int st,dr;
    int maxim;
};

vector<path> paths;

class arbint
{
public:
    vector<elem> arb;
    int nr;

    arbint(int s)
    {
        arb.clear();
        nr=s;
    }

    void create(int s)
    {
        arb.resize(4*s);
    }

    void build(int st,int dr,int nod)
    {
        arb[nod].dr=dr;
        arb[nod].st=st;
        if(st==dr)
        {
            arb[nod].maxim=v[paths[nr].noduri[st]];
            return;
        }
        int mijl=(st+dr)>>1;
        build(st,mijl,nod<<1);
        build(mijl+1,dr,(nod<<1)+1);
        arb[nod].maxim=max(arb[nod<<1].maxim,arb[(nod<<1)+1].maxim);
    }

    void update(int unde,int val,int nod)
    {
        if(arb[nod].st==unde && arb[nod].dr==unde)
        {
            arb[nod].maxim=val;
            return;
        }

        int mijl=(arb[nod].st+arb[nod].dr)>>1;
        if(unde<=mijl)
            update(unde,val,nod<<1);
        else
            update(unde,val,(nod<<1)+1);
        arb[nod].maxim=max(arb[nod<<1].maxim,arb[(nod<<1)+1].maxim);
    }

    int query(int st,int dr,int nod)
    {
        //cout<<"query("<<st<<' '<<dr<<' '<<nod<<")\n";
        if(arb[nod].st==st && arb[nod].dr==dr)
            return arb[nod].maxim;
        int mijl=(arb[nod].st+arb[nod].dr)>>1;
        if(dr<=mijl)
            return query(st,dr,nod<<1);
        else if(st>mijl)
            return query(st,dr,(nod<<1)+1);
        else
            return max(query(st,mijl,nod<<1),query(mijl+1,dr,(nod<<1)+1));
    }
};

vector<arbint> arbori;

void dfs(int nod,int father)
{
    for(vector<int>::iterator it=graf[nod].begin();it!=graf[nod].end();it++)
        if(*it!=father)
        {
            deph[*it]=deph[nod]+1;
            dfs(*it,nod);
            gsize[nod]+=gsize[*it];
        }

    if(!gsize[nod])
    {
        path nou;
        nou.father=0;
        nou.noduri.push_back(nod);
        what_path[nod]=paths.size();

        paths.push_back(nou);
    }
    else
    {
        int maxim=0,cine=0;
        for(vector<int>::iterator it=graf[nod].begin();it!=graf[nod].end();it++)
            if(*it!=father && gsize[*it]>maxim)
                maxim=gsize[*it],cine=*it;
        what_path[nod]=what_path[cine];
        paths[what_path[cine]].noduri.push_back(nod);

        for(vector<int>::iterator it=graf[nod].begin();it!=graf[nod].end();it++)
            if(*it!=father && *it!=cine)
                paths[what_path[*it]].father=nod;
    }
    gsize[nod]++;
}

int lca(int x,int y)
{
    //cout<<"lca("<<x<<","<<y<<")\n";
    if(what_path[x]==what_path[y])
    {
        //cout<<"da"<<endl;
        if(deph[x]>deph[y])
            swap(x,y);
        //cout<<arbori[what_path[x]].query(what_poz[x],what_poz[y],1)<<" OKOKOK!"<<endl;
        return arbori[what_path[x]].query(what_poz[x],what_poz[y],1);
    }
    if(deph[paths[what_path[x]].father]<deph[paths[what_path[y]].father])
        swap(x,y);
    return max(arbori[what_path[x]].query(0,what_poz[x],1),lca(paths[what_path[x]].father,y));
}

int main()
{
    ifstream cin("heavypath.in");
    ofstream cout("heavypath.out");

    int n=0,m=0,a,b,i;

    cin>>n>>m;
    for(i=1;i<=n;i++)
        cin>>v[i];

    for(i=1;i<n;i++)
    {
        cin>>a>>b;
        graf[a].push_back(b);
        graf[b].push_back(a);
    }

    deph[1]=1;
    dfs(1,0);

    vector<path>::iterator it;
    int j;

    for(j=0,it=paths.begin();it!=paths.end();it++,j++)
    {
        reverse(it->noduri.begin(),it->noduri.end());
        vector<int>::iterator it2;

        for(it2=it->noduri.begin(),i=0;it2!=it->noduri.end();i++,it2++)
            what_poz[*it2]=i;

        arbint x(j);
        arbori.push_back(x);

        arbori[j].create(it->noduri.size());
        arbori[j].build(0,it->noduri.size()-1,1);
    }

    bool tip;
    for(i=0;i<m;i++)
    {
        cin>>tip>>a>>b;

        if(tip)
            cout<<lca(a,b)<<'\n';
        else
            arbori[what_path[a]].update(what_poz[a],b,1);
    }

    cin.close();
    cout.close();
    return 0;
}