Nu aveti permisiuni pentru a descarca fisierul grader_test1.in
Cod sursa(job #3258840)
Utilizator | 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;
}