传送门:
http://www.lydsy.com/JudgeOnline/problem.php?id=1146
蒟蒻刷了两天啊!!!!!!!!!
尼玛两天啊!!!!!!!!!!!
重写三遍啊!!!!!!!!!!!
346行代码啊!!!!!!!!!!
链剖+树套树啊!!!!!!!!!
30sT成翔啊!!!!!!!!!!!
================================================================================================================
感想发表完毕
=================================================================================================================
不多说了,看代码吧,附赠数据生成器
Code:
#include<vector> #include<cstdio> #include<climits> #include<iostream> #include<algorithm> #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define L (i<<1) #define R (i<<1|1) const int maxn=80010; const int INF=INT_MAX; using namespace std; typedef pair<int,int> pii; vector<int>G[maxn]; int What; int dep[maxn],son[maxn],siz[maxn],fa[maxn],top[maxn],w[maxn],z=0,a[maxn],b[maxn]; int rnd(){ static int KEY=12345678; return KEY+=KEY<<2|1; } void add(int u,int v){ G[u].push_back(v); G[v].push_back(u); } int n,m; pii road[10001]; int Left,Right,Find; struct Treap{ struct node{ int val;int key,size,s; node *c[2]; node(int _val,node *C){ val=_val;key=rand(); size=1;s=1; c[0]=c[1]=C; } void rz(){ size=c[0]->size+c[1]->size+s; } }; node *root,*Null; Treap(){ Null=new node(0,0); Null->size=0;Null->key=INF;Null->val=0; Null->c[0]=Null->c[1]=Null; root=Null; } void rot(node *&t,bool d){ node *p=t->c[d]; t->c[d]=p->c[!d]; p->c[!d]=t; t->rz();p->rz(); t=p; } void _insert(node *&t,int x){ if(t==Null){ t=new node(x,Null); return ; } if(t->val==x){ t->s++; t->size++; return; } bool d=x>t->val; _insert(t->c[d],x); if(t->c[d]->key<t->key) rot(t,d); else t->rz(); } void _Delete(node *&t,int x){ if(t==Null)return; if(t->val==x){ if(t->s>1){ t->s--; t->size--; return; } bool d=t->c[1]->key<t->c[0]->key; if(t->c[d]==Null){ delete t; t=Null; return ; } rot(t,d); _Delete(t->c[!d],x); }else{ bool d=x>t->val; _Delete(t->c[d],x); } t->rz(); } int _kth(node *&t,int x){ int r=t->c[0]->size; if(t==Null)return 0; else if(x<=r)return _kth(t->c[0],x); else if(x>r+t->s)return _kth(t->c[1],x-r-t->s); else return t->val; } int _rank(node *&t,int x){ int r=t->c[0]->size; if(t==Null)return 0; else if(x==t->val){Find=1;return r;} else if(x>t->val){Right++;return r+t->s+_rank(t->c[1],x);} else{Left++;return _rank(t->c[0],x);} } void _deb(node *&t){ printf("val:%d L:%d R:%d\n",t->val,t->c[0]->val,t->c[1]->val); //printf("key:%d L:%d R:%d\n",t->key,t->c[0]->key,t->c[1]->key); printf("size:%d L:%d R:%d\n",t->size,t->c[0]->size,t->c[1]->size); if(t->c[0]!=Null)_deb(t->c[0]); if(t->c[1]!=Null)_deb(t->c[1]); } void deb(){_deb(root);puts("");} void insert(int x){_insert(root,x);} void del(int x){_Delete(root,x);} int kth(int x){return _kth(root,x);} int rank(int x){return _rank(root,x);} int size(){return root->size;} int _prev(node *&t,int x){ if(t==Null)return INT_MIN; if(x<=t->val)return _prev(t->c[0],x); return max(t->val,_prev(t->c[1],x)); } int _next(node *&t,int x){ if(t==Null)return INT_MAX; if(x>=t->val)return _next(t->c[1],x); return min(t->val,_next(t->c[0],x)); } int prev(int x){ return _prev(root,x); } int next(int x){ return _next(root,x); } }; struct seg_tree{ Treap t[maxn<<2]; void build(int i,int l,int r){ if(l>r)return; for(int o=l;o<=r;o++){ t[i].insert(a[o]); printf("#%d o:%d a[o]:%d",i,o,a[o]); } if(l==r)return; int mid=l+r>>1; build(lson); build(rson); } void change(int i,int l,int r,int pos,int val){ if(l>r)return; //printf("#%d pos:%d val:%d\n",i,pos,val); //puts("old"); //t[i].deb(); t[i].del(a[pos]); //a[pos]=val; //puts("new"); t[i].insert(val); //t[i].deb(); if(l==r){ a[pos]=val; return; } int mid=l+r>>1; if(pos<=mid)change(lson,pos,val); else change(rson,pos,val); } int rank(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=0; if(l0<=l&&r0>=r) return t[i].rank(k); int mid=l+r>>1; if(l0<=mid)ans+=rank(lson,l0,r0,k); if(r0>mid) ans+=rank(rson,l0,r0,k); return ans; } int prev(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=INT_MIN; if(l0<=l&&r0>=r) return t[i].prev(k); int mid=l+r>>1; if(l0<=mid)ans=max(ans,prev(lson,l0,r0,k)); if(r0>mid) ans=max(ans,prev(rson,l0,r0,k)); return ans; } int next(int i,int l,int r,int l0,int r0,int k){ if(l>r)return 0; int ans=INT_MAX; if(l0<=l&&r0>=r) return t[i].next(k); int mid=l+r>>1; if(l0<=mid)ans=min(ans,next(lson,l0,r0,k)); if(r0>mid) ans=min(ans,next(rson,l0,r0,k)); return ans; } }T; namespace TRT{ void Change(int pos,int k){ T.change(1,1,n,pos,k); } int Rank(int l,int r,int k){ Left=Right=Find=0; int res=T.rank(1,1,n,l,r,k); if(Find)return res; if(Left==0)return res; if(Right==0)return res-1; return res; } int kth(int l0,int r0,int k){ int l=0,r=int(1e8)+10; while(l<r){ int mid=l+r>>1; if(Rank(l0,r0,mid)<=k) l=mid+1; else r=mid; } return l-1; } int prev(int l,int r,int k){ return T.prev(1,1,n,l,r,k); } int next(int l,int r,int k){ return T.next(1,1,n,l,r,k); } }; namespace TOPL{ void dfs(int u){ son[u]=0;siz[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]){ dep[v]=dep[u]+1; fa[v]=u; dfs(v); if(siz[v]>siz[son[u]])son[u]=v; siz[u]+=siz[v]; } } } void build(int u,int tp){ w[u]=++z;top[u]=tp; if(son[u])build(son[u],tp); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]&&v!=son[u]) build(v,v); } } void Change(int pos,int val){ TRT::Change(w[pos],val); } int len(int u,int v){ What=0; while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]]){ road[++What]=pii(u,top[u]); u=fa[top[u]]; }else{ road[++What]=pii(v,top[v]); v=fa[top[v]]; } } road[++What]=pii(u,v); int ans=0; for(int i=1;i<=What;i++){ u=road[i].first;v=road[i].second; if(u>v)swap(u,v); ans+=abs(dep[u]-dep[v])+1; } return ans; } int Rank(int u,int v,int k){ What=0;int tmp; while(top[u]!=top[v]){ if(dep[top[u]]>dep[top[v]]){ road[++What]=pii(w[u],w[top[u]]); u=fa[top[u]]; }else{ road[++What]=pii(w[v],w[top[v]]); v=fa[top[v]]; } } road[++What]=pii(w[u],w[v]); int ans=0; for(int i=1;i<=What;i++){ u=road[i].first;v=road[i].second; if(u>v)swap(u,v); tmp=TRT::Rank(u,v,k); if(~tmp)ans+=tmp; } return ans; } void Kth(int u,int v,int k){ k=len(u,v)-k+1;if(k<=0){ puts("invalid request!");return; } int l=0,r=(1e8),mid; while(l<r){ mid=l+r>>1; int rr=Rank(u,v,mid); if(rr<k) l=mid+1; else r=mid; } printf("%d\n",l-1); } }; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; a[i]=-1; // Change(i,a[i]); } for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); add(u,v); } TOPL::dfs(1);TOPL::build(1,1); for(int i=1;i<=n;i++){ TOPL::Change(i,b[i]); } int k,a,b; while(m--){ scanf("%d%d%d",&k,&a,&b); if(k==0){ TOPL::Change(a,b); }else{ TOPL::Kth(a,b,k); } } return 0; }
附赠数据生成器:
#include<cstdio> #include<cstdlib> #include<iostream> #include<ctime> #include<algorithm> using namespace std; int main(){ int a[2101]; srand(time(0)); freopen("1.txt","w",stdout); int n=500,m=1000; cout<<n<<" "<<m<<endl; for(int i=1;i<=n;i++) cout<<(a[i]=rand()%5+1)<<" "; cout<<endl; for(int i=2;i<=n;i++){ cout<<i<<" "<<rand()%(i-1)+1<<endl; } while(m--){ int l=rand()%n+1; int r=rand()%n+1; if(l>r)swap(l,r); int k=rand()%(r-l+1); cout<<k<<" "<<l<<" "<<r<<endl; } return 0; }