题意很简单:在一颗树上修改某个点的值,然后查询两点之间路径上的第k大的元素

查阅了很多资料,因为不会Treap,链接如下:

http://blog.csdn.net/ssccode/article/details/17351461 (这个代码有点问题。比如未删除分配的空间。update顺序错误等。但是写成类的形式很爽。)
http://blog.csdn.net/acdreamers/article/details/11309971
http://www.nocow.cn/index.php/Treap

注:如果rotate看不懂的话 你需要注意参数 node *&x的意义

代码有点长,如下:

//author: CHC
//First Edit Time: 2015-06-06 09:14
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
#include <map>
#include <queue>
#include <set>
#include <algorithm>
#include <limits>
using namespace std;
typedef long long LL;
const int MAXN=80000+1000;
const int INF = numeric_limits<int>::max();
const LL LL_INF= numeric_limits<LL>::max();
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;}
void fixch(node *left,node *right){ch[0]=left;ch[1]=right;}
};
node *root,*null;
Treap(){
null=new node(0,0);
null->fixch(null,null); null->sz=0;
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=(t->v < val);
__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(t->v==val){
bool d=t->ch[1]->p < t->ch[0]->p;
if(t->ch[d]==null){
node *tmp=t;
t=t->ch[!d];
delete tmp;
return ;
}
rotate(t,d);
__del(t->ch[!d],val);
}
else {
bool d=(t->v < val);
__del(t->ch[d],val);
}
t->update();
}
int __rank(node *t,int val){
if(t==null)return 0;
if(t->v < val)return __rank(t->ch[1],val);
return t->ch[1]->sz+1+__rank(t->ch[0],val);
}
void __clean(node *&t){
if(t==null)return ;
if(t->ch[0]!=null)__clean(t->ch[0]);
if(t->ch[1]!=null)__clean(t->ch[1]);
delete t;
t=null;
}
void insert(int val){ __insert(root,val); }
void del(int val){ __del(root,val); }
int rank(int val){ return __rank(root,val);}
void clean(){ __clean(root); }
~Treap(){ clean(); delete null; }
};
struct Edge {
int to,next;
Edge(){}
Edge(int _to,int _next):to(_to),next(_next){}
}e[MAXN<<1];
int head[MAXN],tot;
void AddEdge(int u,int v){
e[tot]=Edge(v,head[u]);
head[u]=tot++;
e[tot]=Edge(u,head[v]);
head[v]=tot++;
}
int dep[MAXN],fa[MAXN],son[MAXN],sz[MAXN];
int top[MAXN],tid[MAXN],ranked[MAXN],tim;
void init(){
memset(head,-1,sizeof(head));
tim=tot=0;
}
void dfs1(int u,int father,int d){
fa[u]=father;dep[u]=d;son[u]=-1;sz[u]=1;
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(fa[u]!=v){
dfs1(v,u,d+1);
sz[u]+=sz[v];
if(son[u]==-1||sz[v]>sz[son[u]])son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;tid[u]=++tim;ranked[tid[u]]=u;
if(son[u]==-1)return ;
dfs2(son[u],tp);
for(int i=head[u];~i;i=e[i].next){
int v=e[i].to;
if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
}
}
Treap treap[MAXN<<2];
int A[MAXN];
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
void build(int L,int R,int rt){
treap[rt].clean();
for(int i=L;i<=R;i++){
treap[rt].insert(A[ranked[i]]);
}
if(L==R)return ;
int mid=(L+R)>>1;
build(lson);build(rson);
}
int query(int L,int R,int rt,int l,int r,int v){
if(l<=L&&R<=r){
return treap[rt].rank(v);
}
int mid=(L+R)>>1,ans=0;
if(l<=mid)ans+=query(lson,l,r,v);
if(r>mid)ans+=query(rson,l,r,v);
return ans;
}
void update(int L,int R,int rt,int pos,int pre,int now){
treap[rt].del(pre);
treap[rt].insert(now);
if(L==R)return ;
int mid=(L+R)>>1;
if(pos<=mid)update(lson,pos,pre,now);
else update(rson,pos,pre,now);
}
int n,q;
int queryx(int x,int y,int v){
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans+=query(1,n,1,tid[top[x]],tid[x],v);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans+=query(1,n,1,tid[x],tid[y],v);
return ans;
}
void updatex(int pos,int v){
update(1,n,1,tid[pos],A[pos],v);
A[pos]=v;
}
int main()
{
while(~scanf("%d%d",&n,&q)){
init();
for(int i=1;i<=n;i++)scanf("%d",&A[i]);
for(int i=0,x,y;i<n-1;i++){
scanf("%d%d",&x,&y);
AddEdge(x,y);
}
dfs1(1,0,0);
//puts("here");
dfs2(1,1);
build(1,n,1);
for(int i=0,x,y,k;i<q;i++){
scanf("%d%d%d",&k,&x,&y);
if(k){
int l=0,r=1e+9,ans=-1;
while(l<=r){
int mid=(l+r)>>1;
int tmp1=queryx(x,y,mid);
if(tmp1<k){
ans=mid;
r=mid-1;
}
else l=mid+1;
}
if(ans-1>=0) printf("%d\n",ans-1);
else puts("invalid request!");
}
else updatex(x,y);
}
}
return 0;
}