http://www.lydsy.com/JudgeOnline/problem.php?id=1146
以前看来是一道神题,今天终于A了
二分+树链剖分+树套树 4个log 2333333
由于写得非常模块化,所以代码写起来有点长,但是写完了只改了两个地方!!!
除了模板部分习惯性缩了行,其余没有缩行,但tmTreap的del函数都写错了,真是该死
蒟蒻太懒没有离散化所以慢了点
思路写得很清晰,以后写主席树
我貌似很落后诶、、、
//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;
/************************************************
Code By willinglive Blog:http://willinglive.cf
************************************************/
#define rep(i,l,r) for(int i=(l),___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=(r),___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
inline const int read()
{int r=0,k=1;char c=getchar();for(;c<'0'||c>'9';c=getchar())if(c=='-')k=-1;
for(;c>='0'&&c<='9';c=getchar())r=r*10+c-'0';return k*r;}
/
const int N=80008;
int n,q;
inline int rnd(){return rand()<<16|rand();}
/
namespace Tree
{ //
int T[N];
struct edge{int v,w,next;}e[N*2];
int head[N],k;
void adde(int u,int v){e[k].v=v;e[k].next=head[u];head[u]=k++;}
int sz[N],fa[N],son[N],dep[N];
int top[N],id[N],cnt;
} ///
namespace Treap
{ ///
#define LS T[o].l
#define RS T[o].r
struct node{int l,r,s,cnt,rnd,x;}T[4000000];
int sz;
void update(int o){T[o].s=T[LS].s+T[RS].s+T[o].cnt;}
void l_rot(int &o){int t=RS;RS=T[t].l;T[t].l=o;T[t].s=T[o].s;update(o);o=t;}
void r_rot(int &o){int t=LS;LS=T[t].r;T[t].r=o;T[t].s=T[o].s;update(o);o=t;}
void insert(int &o,int x)
{
if(!o)
{
o=++sz; T[o].l=T[o].r=0; T[o].s=T[o].cnt=1; T[o].x=x; T[o].rnd=rnd();
return;
}
T[o].s++;
if(x<T[o].x)
{
insert(LS,x);
if(T[LS].rnd<T[o].rnd) r_rot(o);
}
else if(x>T[o].x)
{
insert(RS,x);
if(T[RS].rnd<T[o].rnd) l_rot(o);
}
else T[o].cnt++;
}
void del(int &o,int x)
{
if(!o) return;
if(T[o].x==x)
{
if(T[o].cnt>1) T[o].cnt--,T[o].s--;
else if(LS==0||RS==0) o=LS+RS;
else if(T[LS].rnd<T[RS].rnd) r_rot(o),del(o,x);
else l_rot(o),del(o,x);
return;
}
T[o].s--;
if(x<T[o].x) del(LS,x);
else del(RS,x);
}
int getrank(int o,int x)//>=x
{
if(!o) return 0;
if(x<T[o].x) return T[RS].s+T[o].cnt+getrank(LS,x);
else if(x>T[o].x) return getrank(RS,x);
else return T[RS].s+T[o].cnt;
}
#undef LS
#undef RS
} ///
namespace SGT
{ //
#define LS o<<1,L,mid
#define RS o<<1|1,mid+1,R
int root[300000],tot;
int id_1[N];
void build(int o,int L,int R)
{
rep(i,L,R) Treap::insert(root[o],Tree::T[id_1[i]]);
if(L==R) return;
int mid=L+R>>1;
build(LS); build(RS);
}
void modify(int pos,int x,int o,int L,int R)
{
Treap::del(root[o],Tree::T[id_1[pos]]);
Treap::insert(root[o],x);
if(L==R) return;
int mid=L+R>>1;
if(pos<=mid) modify(pos,x,LS);
else modify(pos,x,RS);
}
int getrank(int x,int l,int r,int o,int L,int R)
{
if(l<=L && R<=r)
{
return Treap::getrank(root[o],x);
}
int mid=L+R>>1;
if(r<=mid) return getrank(x,l,r,LS);
else if(l>mid) return getrank(x,l,r,RS);
else return getrank(x,l,mid,LS)+getrank(x,mid+1,r,RS);
}
} ///
namespace Tree
{ //
void dfs1(int u)
{
sz[u]=1; son[u]=0;
INE(i,u,e)
{
int v=e[i].v; if(v==fa[u]) continue;
fa[v]=u; dep[v]=dep[u]+1;
dfs1(v);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp; id[u]=++cnt;
if(son[u]) dfs2(son[u],tp);
INE(i,u,e)
{
int v=e[i].v; if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void init()
{
using namespace SGT;
dfs1(1); dfs2(1,1);
rep(i,1,n) id_1[id[i]]=i;
build(1,1,n);
}
inline void modify(int u,int x)
{
SGT::modify(id[u],x,1,1,cnt);
T[u]=x;
}
int getrank(int a,int b,int x)
{
int ta=top[a],tb=top[b];
int ans=0;
while(ta^tb)
{
if(dep[ta]<dep[tb]) swap(a,b),swap(ta,tb);
ans+=SGT::getrank(x,id[ta],id[a],1,1,cnt);
a=fa[ta]; ta=top[a];
}
if(dep[a]>dep[b]) swap(a,b);
return ans+SGT::getrank(x,id[a],id[b],1,1,cnt);
}
int query(int a,int b,int k)
{
if(getrank(a,b,0)<k) return -1;
int l=0,r=100000000,mid;
while(l<r)
{
mid=l+r+1>>1;
if(getrank(a,b,mid)<k) r=mid-1;
else l=mid;
}
return l;
}
} ///
/
void input()
{
using namespace Tree;
MS(head,-1);
n=read(); q=read();
rep(i,1,n) T[i]=read();
int u,v;
rep(i,1,n-1)
{
u=read(); v=read();
adde(u,v); adde(v,u);
}
}
void solve()
{
using namespace Tree;
int k,a,b;
init();
while(q--)
{
k=read(); a=read(); b=read();
if(!k)
{
modify(a,b);
}
else
{
int ret=query(a,b,k);
if(ret!=-1) printf("%d\n",query(a,b,k));
else puts("invalid request!");
}
}
}
/
int main()
{
#ifndef _TEST
freopen("std.in","r",stdin); freopen("std.out","w",stdout);
#endif
input(),solve();
return 0;
}