Cod sursa(job #1899979)

Utilizator ZeBuGgErCasapu Andreas ZeBuGgEr Data 3 martie 2017 08:18:51
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.85 kb
#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;

int n,m,t;
int val[100010];
int tata[100010];
int chain_top[100010];
int chain_weight[100010];
int weight[100010];
bool vis[100010];
vector<int> adj[100010];
vector<int> tree[100010];
int belongs_to_chain[100010];
int place_in_chain[100010];
int chain_count;
int lvl[100010];

void decomposition(int node, int level)
{
    vis[node]=1;
    lvl[node]=level;
    int max_weight=0;
    int id=0;
    weight[node]=1;
    for(vector<int>::iterator it=adj[node].begin();it!=adj[node].end();it++)
    {
        if(vis[*it]==0)
        {
            tata[*it]=node;
            decomposition(*it,level+1);
            weight[node]+=weight[*it];
            if(max_weight<weight[*it])
            {
                max_weight=weight[*it];
                id=*it;
            }
        }
    }
    if(max_weight==0)
    {
        chain_count++;
        place_in_chain[node]=1;
        chain_weight[chain_count]=1;
        belongs_to_chain[node]=chain_count;
        chain_top[chain_count]=node;
    }
    else
    {
        place_in_chain[node]=place_in_chain[id]+1;;
        chain_weight[belongs_to_chain[id]]++;
        belongs_to_chain[node]=belongs_to_chain[id];
        chain_top[belongs_to_chain[node]]=node;
    }
}

void update(int chain, int st, int dr, int node, int pos)
{
    if(st==dr)
    {
        tree[chain][node]=val[pos];
        return;
    }
    int m=(st+dr)/2;
    if(place_in_chain[pos]<=m)
    {
        update(chain,st,m,node*2,pos);
    }
    else
    {
        update(chain,m+1,dr,node*2+1,pos);
    }
    tree[chain][node]=max(tree[chain][node*2],tree[chain][node*2+1]);
}

int querry(int chain, int srchl, int srchr, int st, int dr, int node)
{
    if(srchl<=st&&srchr>=dr)
    {
        return tree[chain][node];
    }
    else
    {
        int v1=0,v2=0;
        int m=(st+dr)/2;
        if(srchl>m)
        {
            return querry(chain,srchl,srchr,m+1,dr,node*2+1);
        }
        else if(srchr<=m)
        {
            return querry(chain,srchl,srchr,st,m,node*2);
        }
        else
        {
            return max(querry(chain,m+1,srchr,m+1,dr,node*2+1),querry(chain,srchl,m,st,m,node*2));
        }
    }
}

int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);

    scanf("%d %d",&n,&m);

    for(int i=1;i<=n;i++)
    {
        scanf("%d",&val[i]);
    }

    int x,y;
    for(int i=1;i<n;i++)
    {
        scanf("%d %d",&x,&y);
        adj[x].push_back(y);
        adj[y].push_back(x);
    }

    decomposition(1,1);
    //update(belongs_to_chain[1],1,chain_weight[belongs_to_chain[1]],1,1);
    for(int i=1;i<=chain_count;i++)
    {
        tree[i].resize(4*chain_weight[i]+1);
    }
    for(int i=1;i<=n;i++)
    {
        update(belongs_to_chain[i],1,chain_weight[belongs_to_chain[i]],1,i);
    }

    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&t,&x,&y);
        if(t==0)
        {
            val[x]=y;
            update(belongs_to_chain[x],1,chain_weight[belongs_to_chain[y]],1,x);
        }
        else
        {
            int ma=0;
            while(belongs_to_chain[x]!=belongs_to_chain[y])
            {
                if(lvl[chain_top[belongs_to_chain[x]]]<lvl[chain_top[belongs_to_chain[y]]])
                {
                    swap(x,y);
                }
                ma=max(ma,querry(belongs_to_chain[x],place_in_chain[x],chain_weight[belongs_to_chain[x]],1,chain_weight[belongs_to_chain[x]],1));
                x=tata[chain_top[belongs_to_chain[x]]];
            }
            ma=max(ma,querry(belongs_to_chain[x],min(place_in_chain[x],place_in_chain[y]),max(place_in_chain[x],place_in_chain[y]),1,chain_weight[belongs_to_chain[x]],1));
            printf("%d\n",ma);
        }
    }
}