传送门:
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;
}