标签:div 序列 set 最小 printf 表示 val ras hup
回忆一下序列LIS,$f_i$表示长度为$i$的LIS的最大数最小是多少,每次找到$f_{1\cdots i-1}$中第一个$\geq a_i$的位置并用$a_i$更新它
搬到树上是差不多的,我们用multiset维护每个子树内的DP值,因为子树之间互不影响所以可以直接合并multiset,最后再用根去更新multiset
感觉挺久没打treap所以练练手,1A海星
#include<stdio.h>
#include<stdlib.h>
int l[400010],r[400010],fix[400010],v[400010],siz[400010],M;
void pushup(int x){siz[x]=siz[l[x]]+siz[r[x]]+1;}
struct pr{
int l,r;
pr(int a=0,int b=0){l=a;r=b;}
};
pr splitk(int x,int k){
if(x==0)return pr();
pr s;
if(k<=siz[l[x]]){
s=splitk(l[x],k);
l[x]=s.r;
s.r=x;
}else{
s=splitk(r[x],k-siz[l[x]]-1);
r[x]=s.l;
s.l=x;
}
pushup(x);
return s;
}
pr splitv(int x,int d){
if(x==0)return pr();
pr s;
if(d<v[x]){
s=splitv(l[x],d);
l[x]=s.r;
s.r=x;
}else{
s=splitv(r[x],d);
r[x]=s.l;
s.l=x;
}
pushup(x);
return s;
}
void swap(int&a,int&b){a^=b^=a^=b;}
int merge(int x,int y){
if(x==0)return y;
if(y==0)return x;
if(fix[x]>fix[y])swap(x,y);
pr s=splitv(y,v[x]);
l[x]=merge(l[x],s.l);
r[x]=merge(r[x],s.r);
pushup(x);
return x;
}
int insert(int x,int d){
M++;
fix[M]=rand();
v[M]=d;
siz[M]=1;
pr s=splitv(x,d);
return merge(merge(s.l,M),s.r);
}
int erase(int x,int d){
pr s=splitv(x,d-1);
return merge(s.l,splitk(s.r,1).r);
}
int h[200010],nex[200010],to[200010],val[200010];
void add(int a,int b){
M++;
to[M]=b;
nex[M]=h[a];
h[a]=M;
}
int rt[200010];
void dfs(int x){
for(int i=h[x];i;i=nex[i]){
dfs(to[i]);
rt[x]=merge(rt[x],rt[to[i]]);
}
rt[x]=erase(rt[x],val[x]);
rt[x]=insert(rt[x],val[x]);
}
int main(){
srand(19260817);
int n,i,x,r;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d%d",val+i,&x);
if(x)
add(x,i);
else
r=i;
}
M=0;
dfs(r);
printf("%d",siz[rt[r]]);
}
标签:div 序列 set 最小 printf 表示 val ras hup
原文地址:https://www.cnblogs.com/jefflyy/p/8870168.html