题目很好理解,因为是汉语的。。。
就是求树上的一条路径的第K大数,可修改,多组询问,当然了,对于每组询问,o(n)的时间复杂度不能接受,只能是log级别的
所以就是树链剖分,加segtree套平衡树,代码挺长的
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
#define mid (L+R>>1)
const int inf=~0u>>1;
const int M = 80010;
class Treap{
public:
struct node{
node *ch[2];
int v,p,sz;
node(int _v,node *n):
v(_v){ch[0]=ch[1]=n;p=rand();sz=1;}
void update(){sz=ch[0]->sz+ch[1]->sz+1;}
};
node *root,*null;
Treap(){
null=new node(0,0);null->sz=0;null->p=inf;
null->ch[0]=null->ch[1]=null;
root=null;
}
void rotate(node *&t,bool d){
node *_t=t->ch[d];
t->ch[d]=_t->ch[!d];
_t->ch[!d]=t;
_t->update();
t->update();
t=_t;
}
void __insert(node *&t,int val){
if(t==null){
t=new node(val,null);
return;
}
bool d=val > t->v;
__insert(t->ch[d],val);
if(t->ch[d]->p < t->p)rotate(t,d);
t->update();
}
void __del(node *&t,int val){
if(t==null)return;
if(val == t->v){
bool d = t->ch[1]->p < t->ch[0]->p;
if(t->ch[d]==null){
delete t;
t=null;
return;
}
rotate(t,d);
__del(t->ch[!d],val);
}else{
bool d=val > t->v;
__del(t->ch[d],val);
}
t->update();
}
int __rank(node *t,int val){
if(t==null)return 0;
if(val > t->v)return __rank(t->ch[1],val);
return t->ch[1]->sz+1+__rank(t->ch[0],val);
}
void insert(int val){
__insert(root,val);
}
void del(int val){
__del(root,val);
}
int rank(int val){
return __rank(root,val);
}
};
class segtree{
public:
Treap *tree[M<<2];
int val[M];
void build(int L,int R,int P){
tree[P] = new Treap;
for(int i=L;i<=R;i++){
tree[P]->insert(val[i]);
}
if(L==R)return ;
build(L,mid,P<<1);
build(mid+1,R,P<<1|1);
}
int query(int L,int R,int P,int l,int r,int val){
if(L==l&&R==r){
return tree[P]->rank(val);
}
int ret=0;
if(l<=mid){
ret+=query(L,mid,P<<1,l,min(mid,r),val);
}
if(r>mid){
ret+=query(mid+1,R,P<<1|1,max(l,mid+1),r,val);
}
return ret;
}
void update(int L,int R,int P,int p,int a,int b){
tree[P]->del(a);
tree[P]->insert(b);
if(L==R)return ;
if(p<=mid){
update(L,mid,P<<1,p,a,b);
}else{
update(mid+1,R,P<<1|1,p,a,b);
}
}
};
int head[M],cnt;
struct Edge{
int u,v,next;
void set(int _u,int _v){
u=_u,v=_v;
next=head[u];
head[u]=cnt++;
}
}edge[M<<1];
segtree *tree;
int son[M],pre[M],dep[M],siz[M],top[M],pos[M],tot;
int val[M],n,m;
void init(){
cnt=tot=0;
memset(head,-1,sizeof(head));
}
void dfs_1(int u,int f,int d){
pre[u]=f,dep[u]=d;
siz[u]=1,son[u]=0;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v!=f){
dfs_1(v,u,d+1);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v])son[u]=v;
}
}
}
void dfs_2(int u,int tp){
top[u]=tp,pos[u]=++tot;
if(son[u])dfs_2(son[u],tp);
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].v;
if(v!=son[u]&&v!=pre[u])dfs_2(v,v);
}
}
int rank(int u,int v,int vall){
int f1=top[u],f2=top[v],ret=0;
while(f1!=f2){
if(dep[f1]<dep[f2])swap(u,v),swap(f1,f2);
ret+=tree->query(1,n,1,pos[f1],pos[u],vall);
u=pre[f1],f1=top[u];
}
if(dep[u]<dep[v])swap(u,v);
return ret+tree->query(1,n,1,pos[v],pos[u],vall);
}
int main(){
while(~scanf("%d%d",&n,&m)){
init();
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
}
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
edge[cnt].set(u,v);
edge[cnt].set(v,u);
}
tree = new segtree;
dfs_1(1,0,1);
dfs_2(1,1);
for(int i=1;i<=n;i++){
tree->val[pos[i]]=val[i];
}
tree->build(1,n,1);
while(m--){
int k,a,b;
scanf("%d%d%d",&k,&a,&b);
if(k){
int L=0,R=(int)1e8,f=0;
while(L<=R&&!f){
int aa=rank(a,b,mid+1);
int bb=rank(a,b,mid);
if(k>aa&&k<=bb){
f=1;
printf("%d\n",mid);
}
k>aa?R=mid-1:L=mid+1;
}
if(!f)puts("invalid request!");
}else{
tree->update(1,n,1,pos[a],val[a],b);
val[a]=b;
}
}
}
return 0;
}