题目很好理解,因为是汉语的。。。
就是求树上的一条路径的第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; }