Cod sursa(job #2642201)

Utilizator MoldovanAndrei1Moldovan Andrei MoldovanAndrei1 Data 13 august 2020 23:33:21
Problema Heavy Path Decomposition Scor 10
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 5.3 kb
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <ctype.h>
#include <cmath>
using namespace std;
const int NMAX = 100005;
vector <int> Edge[NMAX];
int last = 0 , time1 = 0 , n;
int freq[NMAX],size_tree[NMAX],com[NMAX], parent[NMAX],value[NMAX] , Heavy_Edge[NMAX] , poz[NMAX] , start[NMAX],  aint[4*NMAX + 5];
int d[NMAX], parent1[NMAX] , height[NMAX] , best[NMAX] , end1[NMAX] , max_t[NMAX];
int _in_loc; char _in_buff[32768];
char read_ch()
{
	++_in_loc;
	if (_in_loc == 32768) {
		_in_loc = 0;
		fread(_in_buff, 1, 32768, stdin);
	}
	return _in_buff[_in_loc];
}

int read_u32()
{
	int u32 = 0; char c;
	while (!isdigit(c = read_ch()) && c != '-');
	int sgn = 1;
    u32 = c - '0';
	while (isdigit(c = read_ch())) {
		u32 = u32 * 10 + c - '0';
	}
	return u32 * sgn;
}
void dfs(int nod)
{
    freq[nod] = 1;
    vector<int>::iterator it;

    for(it =  Edge[nod] . begin() ; it!= Edge[nod].end();it++)
            if(!freq[*it])
                {
                    d[*it] = d[nod] + 1;
                    parent[*it]=nod;
                    dfs(*it);
                    size_tree[nod]+= size_tree[*it];
                }
    bool ok = 0 ;
    for(it =  Edge[nod] . begin() ; it!= Edge[nod].end();it++)
            if(*it!=parent[nod] && size_tree[*it] >= (size_tree[nod] + 1)/2)
            {
                ok = 1;
                com[nod] = com[*it];
                best[com[*it]] = max(best[com[*it]] , value[nod]);
                Heavy_Edge[*it] = nod;
                break;
            }
    if(!ok)
            {
                com[nod] = ++last;
                best[last] = value[nod];
                start[last] = nod;
            }
    for(it =  Edge[nod] . begin() ; it!= Edge[nod].end();it++)
          if(*it != parent[nod] && com[nod] != com[*it])
            parent1[com[*it]] = nod;
}
void dfs1(int nod)
{
    poz[++time1] = nod;
    height[nod] = time1;
    end1[com[nod]] = nod;
    int t1 = Heavy_Edge[nod];
    if(Heavy_Edge[nod])
      dfs1(Heavy_Edge[nod]) ;
}
void build(int nod , int st ,int dr)
{
    if(st == dr)
    aint[nod] = value[poz[st]];
    else
    {
      int med = (st + dr)>>1;
    build(2*nod,st,med);
    build(2*nod+1,med+1,dr);
      aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }
}
void update(int nod ,int st , int dr , int poz,int val)
{
    if(st == dr)
        aint[nod]=val;
    else
    {
      int med = (st + dr)>>1;
      if(poz<=med)update(2*nod , st,med,poz,val);
      else
            update(2*nod + 1 , med+1,dr,poz,val);
            aint[nod]=max(aint[2*nod],aint[2*nod+1]);
    }
}
int query(int nod ,int st, int dr,int l,int r)
{
    if(l<=st&&dr<=r)
        return aint[nod];
    int med=(st+dr)>>1;
    int a = 0 ,b=0;
    if(l<=med)a=query(2*nod,st,med,l,r);
    if(r>med)
        b=query(2*nod+1,med+1,dr,l,r);
    return max(a,b);
}
int sqparent[NMAX],h;
void dfs2(int nod)
{
    vector<int>::iterator it;
    for(it=Edge[nod].begin();it!=Edge[nod].end();it++)
    {
        if(d[*it]%h==0)sqparent[*it]=nod;
        else
            sqparent[*it]=sqparent[nod];
        dfs2(*it);
    }
}
int naivelca(int u ,int v)
{
    if(d[u]>d[v])swap(u,v);
    if(d[u]==d[v])
    {
        if(u==v)return u;
        u=parent[u];
        v=parent[v];
        return naivelca(u,v);
    }
    v=parent[v];
    return naivelca(u,v);
}
int sqlca(int u,int v)
{
    if(d[u]>d[v])swap(u,v);
    if(sqparent[u]!=sqparent[v])
    {
         return sqlca(u,sqparent[v]);
    }
    return naivelca(u,v);
}
inline int max1(int a,int b)
{
    if(a<b)
        return b;
    return a;
}
inline int min1(int a,int b)
{
    if(a>b)return b;
    return a;
}
int answer(int x , int y)
{
    if(d[x] > d[y]) swap(x , y);
    int x1 = com[x] , y1 = com [y];
    if(x1 == y1)
        return query(1 , 1 , n, min1(height[x] , height[y]), max1(height[x] , height[y]));
        else
    {
        int maxim = 0 , y2 =  parent1[y1];
        while(com[y2] != x1)
        {
            if(y2 )break;
            maxim = max1(maxim , best[com[y2]]);
            y2 = parent1[com[y2]];
        }
        int a = query(1 , 1 , n, min1(height[y2] , height[x]), max1(height[y2],height[x]));
        int b = query(1 , 1 , n, height[y] , height[end1[y1]]);
        maxim = max1(maxim , max1(a,b));
        return maxim;
    }
}
void solve(int x , int y)
{
    int t = sqlca(x , y);

    printf("%d\n",max(answer(x,t) , answer(y, t)));
}
int main()
{
    freopen("heavypath.in","r",stdin);
    freopen("heavypath.out","w",stdout);
    int  q , i , x , y, op;
    n=read_u32();
    q=read_u32();
    h = sqrt(n);
    for( i = 1 ; i <= n; ++i)
           {
               value[i]=read_u32();
               size_tree[i] = 1;
           }
    for( i = 1 ; i < n; i++)
    {
        x = read_u32();
        y = read_u32();
        Edge[x].push_back(y);
        Edge[y].push_back(x);
    }
    d[1] = 1;
    parent[1] = 1;
    dfs(1);
    for(i = 1 ; i <=last ; ++i)
            dfs1(start[i]);
    build(1 , 1, n);
    for(i = 1 ; i <= q; i++)
    {
        op=read_u32();
        x=read_u32();
        y=read_u32();
        if(op == 0)
            update(1 , 1 , n , height[x] , y);
        else
            solve(x,y);
    }
    return 0;
}