鏈接自己找,BZOJ還沒開
題意:求樹上路徑第k大,單點修改,可離線
考慮樹剖維護,內層主席樹外層套個樹狀數組就完了(時空和代碼長度都全方位被整體二分吊打)
也可以整體二分
Code:
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=8e4+5;
int sign[500],tmp[500],tot=0;
int b[N<<1];
namespace president_tree{
struct seg{int l,r,sz;}tr[N*200];int cnt=0;
#define ls(k) tr[k].l
#define rs(k) tr[k].r
#define mid (l+r>>1)
inline void ins(int &rt,int l,int r,int pos,int v){
tr[++cnt]=tr[rt];tr[cnt].sz+=v;rt=cnt;
if(l==r) return;
if(pos<=mid) ins(ls(rt),l,mid,pos,v);
else ins(rs(rt),mid+1,r,pos,v);
}
inline int query(int l,int r,int k){
if(l==r) return l;
int sum=0;
for(int i=1;i<=tot;i++) sum+=tr[rs(tmp[i])].sz*sign[i];
if(k<=sum){
for(int i=1;i<=tot;i++) tmp[i]=rs(tmp[i]);
return query(mid+1,r,k);
}
else{
for(int i=1;i<=tot;i++) tmp[i]=ls(tmp[i]);
return query(l,mid,k-sum);
}
}
}
using president_tree::ins;
using president_tree::query;
int n,nn;
int rt[N];
namespace Bit{
inline int lb(int x){return x&(-x);}
inline void add(int x,int pos,int v){for(int i=x;i<=n;i+=lb(i)) ins(rt[i],1,nn,pos,v);}
inline void mark(int x,int v){for(int i=x;i;i-=lb(i)) tmp[++tot]=rt[i],sign[tot]=v;}
}
using Bit::mark;
namespace treecut{
int vis[N<<1],head[N],nxt[N<<1],etot=0;
inline void add(int x,int y){vis[++etot]=y;nxt[etot]=head[x];head[x]=etot;}
int siz[N],hson[N],dep[N],fa[N];
void dfs1(int v){
siz[v]=1;
for(int i=head[v];i;i=nxt[i]){
int y=vis[i];
if(y==fa[v]) continue;
fa[y]=v;dep[y]=dep[v]+1;
dfs1(y);
siz[v]+=siz[y];
if(siz[y]>siz[hson[v]]) hson[v]=y;
}
}
int top[N],dfn[N],sign=0,id[N];
void dfs2(int v){
dfn[v]=++sign;id[sign]=v;
if(hson[v]) top[hson[v]]=top[v],dfs2(hson[v]);
for(int i=head[v];i;i=nxt[i])
if(!top[vis[i]]) top[vis[i]]=vis[i],dfs2(vis[i]);
}
inline void query_path(int x,int y,int k){
tot=0;int cur=dep[x]+dep[y]+1;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
mark(dfn[top[x]]-1,-1);mark(dfn[x],1);x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
mark(dfn[y]-1,-1);mark(dfn[x],1);
cur-=2*dep[y];
if(cur<k) puts("invalid request!");
else cout<<b[query(1,nn,k)]<<"\n";
}
}
using namespace treecut;
int val[N];
struct Q{int k,a,b;}q[N];
int main(){
nn=n=read();int m=read();
for(int i=1;i<=n;i++) val[i]=b[i]=read();
for(int x,y,i=1;i<n;i++){
x=read(),y=read();
add(x,y);add(y,x);
}
for(int i=1;i<=m;i++){
q[i].k=read(),q[i].a=read(),q[i].b=read();
if(!q[i].k) b[++nn]=q[i].b;
}
sort(b+1,b+nn+1);
nn=unique(b+1,b+nn+1)-b-1;
for(int i=1;i<=n;i++) val[i]=lower_bound(b+1,b+nn+1,val[i])-b;
for(int i=1;i<=m;i++) if(!q[i].k) q[i].b=lower_bound(b+1,b+nn+1,q[i].b)-b;
dep[1]=1;dfs1(1);top[1]=1;dfs2(1);
for(int i=1;i<=n;i++) Bit::add(i,val[id[i]],1);
for(int i=1;i<=m;i++){
if(!q[i].k){
Bit::add(dfn[q[i].a],val[q[i].a],-1);
Bit::add(dfn[q[i].a],q[i].b,1);
val[q[i].a]=q[i].b;
}
else query_path(q[i].a,q[i].b,q[i].k);
}
return 0;
}