#include<bits/stdc++.h>usingnamespace std;#define LL long long#define LD long doubletemplate<typename T>voidread(T &x){
x =0;int f =1;char c =getchar();for(;!isdigit(c); c =getchar())if(c =='-') f =-f;for(;isdigit(c); c =getchar()) x = x *10+ c -'0';
x *= f;}template<typename T>voidchkmax(T &x, T y){ x =max(x, y);}template<typename T>voidchkmin(T &x, T y){ x =min(x, y);}constint N =80010;int n, m, x, y, z, a[N];char opt;struct Segment_Tree
{int rt[N], s[N *300], lc[N *300], rc[N *300];int q[N <<3], tot, top, now, su, sv, sp, sf;voidModify(int&k,int l,int r,int w,int v){if(!k) k =++tot;
s[k]+= v;if(l == r)return;int mid = l + r >>1;if(w <= mid)Modify(lc[k], l, mid, w, v);elseModify(rc[k], mid +1, r, w, v);}intQuery(int k,int l,int r,int w){if(!k)return0;if(w >= r)return s[k];int mid = l + r >>1;if(w <= mid)returnQuery(lc[k], l, mid, w);elsereturn s[lc[k]]+Query(rc[k], mid +1, r, w);}intKth(int u,int v,int p,int f,int k){
top =0;for(int i = u; i; i -= i &-i) q[++top]= rt[i]; su = top;for(int i = v; i; i -= i &-i) q[++top]= rt[i]; sv = top;for(int i = p; i; i -= i &-i) q[++top]= rt[i]; sp = top;for(int i = f; i; i -= i &-i) q[++top]= rt[i]; sf = top;int L =0, R =1e8;for(int mid = L + R >>1, sum; L < R; mid = L + R >>1){
sum =0;for(int i =1; i <= su;++i) sum += s[lc[q[i]]];for(int i = su +1; i <= sv;++i) sum += s[lc[q[i]]];for(int i = sv +1; i <= sp;++i) sum -= s[lc[q[i]]];for(int i = sp +1; i <= sf;++i) sum -= s[lc[q[i]]];if(sum >= k){for(int i =1; i <= top;++i) q[i]= lc[q[i]];
R = mid;}else{for(int i =1; i <= top;++i) q[i]= rc[q[i]];
L = mid +1, k -= sum;}if(L == R)return L;}return R;}} T;struct BIT
{voidModify(int x,int w,int v){for(int i = x; i <= n; i += i &-i) T.Modify(T.rt[i],0,1e8, w, v);}intQuery(int l,int r,int k){int ans =0;for(int i = r; i; i -= i &-i) ans += T.Query(T.rt[i],0,1e8, k);for(int i = l -1; i; i -= i &-i) ans -= T.Query(T.rt[i],0,1e8, k);return ans;}intKth(int u,int v,int p,int fp,int k){return T.Kth(u, v, p, fp, k);}} B;struct edge {int to, nxt;} e[N <<1];constint LG =16;int fa[LG +2][N];int fir[N], dfn[N], id[N], dp[N], lst[N];int cnt, tim, K;voidAde(int u,int v){
e[++cnt]=(edge){ v, fir[u]}, fir[u]= cnt;
e[++cnt]=(edge){ u, fir[v]}, fir[v]= cnt;}voidDfs(int u,int f){
dfn[u]=++tim, id[tim]= u, dp[u]= dp[f]+1;
fa[0][u]= f;for(int i =1; i <= LG;++i)
fa[i][u]= fa[i -1][fa[i -1][u]];for(int i = fir[u]; i; i = e[i].nxt)if(e[i].to != f)Dfs(e[i].to, u);
lst[u]= tim +1;}intLca(int u,int v){if(dp[u]> dp[v])swap(u, v);for(int i = LG; i >=0;--i)if(dp[fa[i][v]]>= dp[u]) v = fa[i][v];if(u == v)return u;for(int i = LG; i >=0;--i)if(fa[i][u]!= fa[i][v]) u = fa[i][u], v = fa[i][v];return fa[0][u];}intmain(){// freopen("test.in", "r", stdin);// freopen("test.out", "w", stdout);read(n),read(m);for(int i =1; i <= n;++i)read(a[i]);for(int i =1; i < n;++i)read(x),read(y),Ade(x, y);Dfs(1,0);for(int i =1; i <= n;++i)
B.Modify(dfn[i], a[i],1),
B.Modify(lst[i], a[i],-1);while(m--){read(K),read(x),read(y);if(K ==0){
B.Modify(dfn[x], a[x],-1);
B.Modify(lst[x], a[x],1);
a[x]= y;
B.Modify(dfn[x], a[x],1);
B.Modify(lst[x], a[x],-1);}else{
z =Lca(x, y);
K = dp[x]+ dp[y]-2* dp[z]- K +2;if(K <=0) cout <<"invalid request!\n";else cout << B.Kth(dfn[x], dfn[y], dfn[z], dfn[fa[0][z]], K)<<'\n';}}return0;}
蒟蒻的第一篇博客[CTSC2008]网络管理 题面解法程序题面题目链接 lg P4175解法题目就是给你一棵树,有点权,每次操作修改一个点的点权,或者查询一条链上的第K大点权。简单来说就是树上带修权值第K大。考虑不在树上,而是在区间上,如果没有修改的化,就是一个裸的主席树加上修改的化,可以发现每次的修改,相当于在[L, R]的区间上都去掉原来权值的影响,在加上新修改的权值的影响,...