将整体二分移到了树上 那么在二分的时候 比较mid的过程 肯定是要用树链剖分+线段树(听说差分+树状数组也能做)来维护大于mid的个数的 然后就是一个整体二分的套路了
修改的时候就是将赋值操作拆分成两个操作 一个把原来的值-1 另一个把新加入的值+1
另外对于没有解的情况我预处理了一下 求了一个lca(x,y) 然后算 x和y之间有几个点 如果小于k就没有 答案 都是比较直接的做法 但是能写出来
离散化了一下值域 保守估计复杂度 nlogn^3
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int in(){
int w=0,x=0;char c=0;
while(c<'0'||c>'9') w|=c=='-',c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
const int N = 8e4+100;
const int M = 3e5+100;
int h[N],nex[N<<1],to[N<<1],cur;
int n,qs,has[M],cnt,val[N],ans[N];
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
#define ls id<<1
#define rs ls|1
#define lson ls,l,mid
#define rson rs,mid+1,r
struct node{
int u,v,k,op;
}q[M],lq[M],rq[M];
struct tree_cut{
int fa[N],tot,dep[N],tp[N],siz[N],son[N],tid[N],rnk[N];
ll sum[N<<2];
void dfs1(int u){
siz[u]=1;
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
if(!dep[v]){
dep[v]=dep[u]+1;
fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int t){
tp[u]=t;tid[u]=++tot;rnk[tot]=u;
if(son[u]) dfs2(son[u],t);
for(int i = h[u]; i; i = nex[i]){
int v = to[i];
if(v==son[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
void pushup(int id){
sum[id]=sum[ls]+sum[rs];
}
void update(int id,int l,int r,int pos,int val){
if(l==r){
sum[id]+=val;
return;
}
int mid = l+r>>1;
if(pos<=mid) update(lson,pos,val);
else update(rson,pos,val);
pushup(id);
}
ll query(int id,int l,int r,int L,int R){
if(L<=l&&R>=r) return sum[id];
ll ans=0;
int mid = l+r>>1;
if(L<=mid) ans+=query(lson,L,R);
if(R>mid) ans+=query(rson,L,R);
return ans;
}
ll que_sum(int u,int v){
ll ans=0;
while(tp[u]!=tp[v]){
if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
ans+=query(1,1,n,tid[tp[u]],tid[u]);
u=fa[tp[u]];
}
if(dep[u]<dep[v]) swap(u,v);
ans+=query(1,1,n,tid[v],tid[u]);
return ans;
}
int lca(int u,int v){
while(tp[u]!=tp[v]){
if(dep[tp[u]]<dep[tp[v]]) swap(u,v);
u=fa[tp[u]];
}
if(dep[u]<dep[v]) swap(u,v);
return v;
}
void solve(int lval,int rval,int st,int ed){
if(st>ed) return;
if(lval==rval){
for(int i = st; i <= ed; i++){
if(q[i].op){
if(ans[q[i].op]==-1) continue;
else ans[q[i].op]=has[lval];
}
}
return;
}
int mid = lval+rval>>1,lt = 0,rt = 0;
for(int i = st; i <= ed; i++){
if(q[i].op==0){
if(q[i].k>has[mid]) rq[++rt]=q[i],update(1,1,n,tid[q[i].u],q[i].v);
else lq[++lt]=q[i];
}else{
ll ct=que_sum(q[i].u,q[i].v);
if(ct>=q[i].k) rq[++rt]=q[i];
else q[i].k-=ct,lq[++lt]=q[i];
}
}
for(int i = 1; i <= lt; i++) q[st+i-1]=lq[i];
for(int i = 1; i <= rt; i++) q[st+lt+i-1]=rq[i];
for(int i = st; i <= ed; i++)
if(q[i].k>has[mid]&&q[i].op==0)
update(1,1,n,tid[q[i].u],-q[i].v);
solve(lval,mid,st,st+lt-1);
solve(mid+1,rval,st+lt,ed);
}
}T;
int main(){
int ts=0;
T.dep[1]=1;
n=in(),qs=in();
for(int i = 1; i <= n; i++){
val[i]=in();
has[++cnt]=val[i];
q[++ts]=(node){i,1,val[i],0};
}
for(int i = 1; i < n; i++){
int u,v;
u=in(),v=in();
add_edge(u,v);
add_edge(v,u);
}
T.dfs1(1);
T.dfs2(1,1);
int qsum=0;
for(int i = 1; i <= qs; i++){
int op,a,b;
op=in(),a=in(),b=in();
if(op==0){
q[++ts]=(node){a,-1,val[a],0};
val[a]=b;
q[++ts]=(node){a,1,val[a],0};
has[++cnt]=b;
}else{
q[++ts]=(node){a,b,op,++qsum};
int lc=T.lca(a,b);
int dis=T.dep[a]+T.dep[b]-T.dep[lc]-T.dep[T.fa[lc]];
if(dis<op) ans[qsum]=-1;
}
}
sort(has+1,has+1+cnt);
cnt=unique(has+1,has+1+cnt)-has-1;
T.solve(1,cnt,1,ts);
for(int i = 1; i <= qsum; i++)
if(ans[i]==-1) puts("invalid request!");
else printf("%d\n",ans[i]);
return 0;
}