Cod sursa(job #2026440)

Utilizator MaarcellKurt Godel Maarcell Data 24 septembrie 2017 14:04:39
Problema Heavy Path Decomposition Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.48 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <ctime>
#include <unordered_map>
#include <iomanip>
using namespace std;

#define fi first
#define se second
#define pb push_back
#define all(v) (v).begin(),(v).end()

typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef pair<int,int> pii;

template<class T> ostream& operator<<(ostream& stream, const vector<T> v){ stream << "["; for (int i=0; i<(int)v.size(); i++) cout << v[i] << " "; stream << "]"; return stream; }
ll fpow(ll x, ll p, ll m){ll r=1; for (;p>>=1;){ if (p&1) r=r*x%m; x=x*x%m; } return r;}
int gcd(int a, int b){ if (!b) return a; return gcd(b,a%b);}
ll gcd(ll a, ll b){ if (!b) return a; return gcd(b,a%b);}

int N,M,a[100100],sz[100100],L,d[100100],lid[100100],pl[100100]; vi g[100100];
int pos[100100],off[100100];

int t[800100];

vi lant[100100];

void bdfs(int nod, int f, int h){
    d[nod]=h;
    sz[nod]=1;

    if ((nod!=1 && g[nod].size()==1) || N==1){
        lid[nod]=++L;
        lant[L].pb(nod);
        return;
    }

    int bst=0;
    for (int nxt : g[nod]){
        if (nxt==f) continue;

        bdfs(nxt,nod,h+1);
        if (sz[bst]<sz[nxt]) bst=nxt;
        sz[nod]+=sz[bst];
    }

    lid[nod]=lid[bst];
    lant[lid[nod]].pb(nod);

    for (int nxt : g[nod])
        if (nxt!=f && nxt!=bst) pl[lid[nxt]]=nod;
}



void upd(int nod, int l, int r, int off, int p, int val){
    if (l==r){
        t[nod+off]=val;
        return ;
    }

    int mid=(l+r)/2;
    if (p<=mid) upd(nod*2,l,mid,off,p,val);
    else upd(nod*2+1,mid+1,r,off,p,val);
    t[nod+off]=max(t[nod*2+off],t[nod*2+1+off]);
}

void upd(int x, int val){
    upd(1,1,lant[lid[x]].size(),off[lid[x]],pos[x],val);
}

int query(int nod, int l, int r, int ql, int qr, int off){
    if (ql<=l && r<=qr) return t[nod+off];

    int mid=(l+r)/2,lv=0,rv=0;
    if (ql<=mid) lv=query(nod*2,l,mid,ql,qr,off);
    if (mid<qr)  rv=query(nod*2+1,mid+1,r,ql,qr,off);

    return max(lv,rv);
}

void build(){
    int i,j;

    bdfs(1,0,1);
    int crsz=0;
    for (i=1; i<=L; i++){
        reverse(all(lant[i]));
        off[i]=crsz;
        for (j=1; j<=(int)lant[i].size(); j++){
            pos[lant[i][j-1]]=j;
            upd(lant[i][j-1],a[lant[i][j-1]]);
        }

        crsz+=4*lant[i].size();
    }
}

int query(int x, int y){
    int res=0;
    while (x!=-1){
        if (d[x]>d[y]) swap(x,y);

        if (lid[x]==lid[y]){
            res=max(res,query(1,1,lant[lid[x]].size(),pos[x],pos[y],off[lid[x]]));
            x=-1;
        }
        else {
            if (d[pl[lid[x]]]<d[pl[lid[y]]]) swap(x,y);

            res=max(res,query(1,1,lant[lid[x]].size(),1,pos[x],off[lid[x]]));
            x=pl[lid[x]];
        }
    }

    return res;
}

int main(){

    ifstream fin("heavypath.in");
    ofstream fout("heavypath.out");
    fin >> N >> M;

    int i;
    for (i=1; i<=N; i++)
        fin >> a[i];

    for (i=1; i<N; i++){
        int x,y;
        fin >> x >> y;
        g[x].pb(y);
        g[y].pb(x);
    }

    build();
    for (int k=1; k<=M; k++){
        cout << k << "\n";
        int t,x,y;
        fin >> t >> x >> y;

        if (t==0){
            a[x]=y;
            upd(x,y);
        }
        else {
            fout << query(x,y) << "\n";
        }
    }

    return 0;
}