平衡树专题题解
A 普通平衡树
B [NOI2005]维修数列
名字好鬼啊
看这里
C [TJOI2013]最长上升子序列
题意:Luogu
题解:设\(dp[i]\)表示以\(i\)结尾的最长上升子序列长度,\(pos[i]\)表示\(i\)节点对应下标,\(val[i]\)表示以\(i\)节点为根的区间的LIS长度
\[val[rt]=max(max(val[ls],val[rs]),dp[pos[rt])
\]
然后就没了
code
D [HNOI2002]营业额统计
题意:Luogu
题解:直接查前驱后继即可。注意要插两个哨兵。
code
E [HNOI2004]宠物收养场
题意:Luogu
题解:建两棵树,一颗宠物一颗人,然后就没了查一下前驱后继,优先前驱
code
F 文艺平衡树
题意:Luogu
题解:没有
话说fhq和线段树挺像的来着
code
G [TJOI2019]甲苯先生的滚榜
诡异的标题
TJOI2019D1T2就是这种水题?
题意:Luogu
题解:就是一个板子(然而我把\(x,y\)封装在里面之后一直WA,设成全局变量就过了???我tm调了两三个小时啊)
另外这题很卡常,读优和输优都要写上
然而我本地还是过不了
然而luogu机子真快啊
code
A code
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
#define ls son[rt][0]
#define rs son[rt][1]
int rnd[maxn],val[maxn],son[maxn][2],siz[maxn];
int tot,root,x,y,z;
inline void read(int& x)
{
x=0;char c=getchar();int f=1;
while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=f;
}
inline void update(int rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
}
void split(int rt,int v,int& x,int& y)
{
if(!rt) x=y=0;
else
{
if(val[rt]<=v)
{
x=rt;
split(rs,v,rs,y);
}
else
{
y=rt;
split(ls,v,x,ls);
}
update(rt);
}
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(rnd[x]<=rnd[y])
{
son[x][1]=merge(son[x][1],y);
update(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
update(y);
return y;
}
}
inline int newnode(int v)
{
siz[++tot]=1;
val[tot]=v;
rnd[tot]=rand();
return tot;
}
inline void insert(int v)
{
split(root,v,x,y);
root=merge(merge(x,newnode(v)),y);
}
inline void pop(int v)
{
split(root,v,x,z);
split(x,v-1,x,y);
y=merge(son[y][0],son[y][1]);
root=merge(merge(x,y),z);
}
inline int getrank(int v)
{
split(root,v-1,x,y);
int ans=siz[x]+1;
root=merge(x,y);
return ans;
}
inline int getkth(int rt,int k)
{
while(true)
{
if(k<=siz[ls]) rt=ls;
else if(k==siz[ls]+1) return rt;
else k-=siz[ls]+1,rt=rs;
}
}
inline int lower(int v)
{
split(root,v-1,x,y);
int ans=val[getkth(x,siz[x])];
merge(x,y);
return ans;
}
inline int upper(int v)
{
split(root,v,x,y);
int ans=val[getkth(y,1)];
merge(x,y);
return ans;
}
int main()
{
srand((unsigned long long)new char);
int n,op,v;
read(n);
for(int i=1;i<=n;++i)
{
read(op),read(v);
if(op==1) insert(v);
else if(op==2) pop(v);
else if(op==3) printf("%d\n",getrank(v));
else if(op==4) printf("%d\n",val[getkth(root,v)]);
else if(op==5) printf("%d\n",lower(v));
else printf("%d\n",upper(v));
}
return 0;
}
C code
#include<bits/stdc++.h>
using namespace std;
inline void read(int& x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
namespace fhqTreap
{
#define maxn 100005
#define ls son[rt][0]
#define rs son[rt][1]
int root,tot,x,y;
int son[maxn][2],siz[maxn],maxval[maxn],val[maxn],rnd[maxn],dp[maxn],pos[maxn];
inline void pushup(const int& rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
val[rt]=max(max(val[ls],val[rs]),dp[pos[rt]]);
}
void split_val(int rt,int v,int& x,int& y)
{
if(!rt) x=y=0;
else
{
if(v>=val[rt]) x=rt,split_val(rs,v,rs,y);
else y=rt,split_val(ls,v,x,ls);
pushup(rt);
}
}
void split_size(int rt,int k,int& x,int& y)
{
if(!rt) x=y=0;
else
{
if(k>siz[ls]) x=rt,split_size(rs,k-siz[ls]-1,rs,y);
else y=rt,split_size(ls,k,x,ls);
pushup(rt);
}
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(rnd[x]<rnd[y])
{
son[x][1]=merge(son[x][1],y);
pushup(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
pushup(y);
return y;
}
}
inline int newnode(const int& v,const int& posi)
{
siz[++tot]=1,rnd[tot]=rand();
pos[tot]=posi,dp[pos[tot]]=val[tot]=v;
return tot;
}
void print(int rt)
{
if(ls) print(ls);
printf("%d ",val[rt]);
if(rs) print(rs);
}
}
using namespace fhqTreap;
int dp[maxn];
int main()
{
srand(time(NULL));
int n,pos;
read(n);
for(int i=1;i<=n;++i)
{
read(pos);
split_size(root,pos,x,y);
root=merge(merge(x,newnode(val[x]+1,i)),y);
printf("%d\n",val[root]);
}
return 0;
}
D code
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
#define inf 0x3f3f3f3f
#define ls son[rt][0]
#define rs son[rt][1]
inline void read(int& x)
{
x=0;char c=getchar();int f=1;
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=f;
}
inline int min(int x,int y)
{
return x<y?x:y;
}
int rnd[maxn],siz[maxn],val[maxn],son[maxn][2],tot,root;
int x,y,z;
inline void update(int rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
}
void split(int rt,int k,int& x,int& y)
{
if(!rt)
{
x=y=0;
return;
}
if(val[rt]<=k) x=rt,split(rs,k,rs,y);
else y=rt,split(ls,k,x,ls);
update(rt);
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(rnd[x]<rnd[y])
{
son[x][1]=merge(son[x][1],y);
update(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
update(y);
return y;
}
}
inline int newnode(int v)
{
siz[++tot]=1;
val[tot]=v;
rnd[tot]=rand();
return tot;
}
inline void insert(int v)
{
split(root,v,x,y);
root=merge(merge(x,newnode(v)),y);
}
inline int getkth(int rt,int k)
{
while(true)
{
if(k<=siz[ls]) rt=ls;
else if(k==siz[ls]+1) return rt;
else k-=siz[ls]+1,rt=rs;
}
}
inline int lower(int v)
{
split(root,v,x,y);
int ans=val[getkth(x,siz[x])];
root=merge(x,y);
return ans;
}
inline int upper(int v)
{
split(root,v,x,y);
int ans=val[getkth(y,1)];
root=merge(x,y);
return ans;
}
inline bool find(int v)
{
return lower(v)==v;
}
int main()
{
srand(time(NULL));
int n,v,ans=0;
read(n);
insert(inf),insert(-inf);
for(int i=1;i<=n;++i)
{
read(v);
if(find(v)) continue;
int pre=lower(v),las=upper(v);
if(pre==-inf&&las==inf) ans+=v;
else if(pre==-inf) ans+=las-v;
else if(las==inf) ans+=v-pre;
else ans+=min(v-pre,las-v);
insert(v);
}
printf("%d\n",ans);
return 0;
}
E code
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
#define P 1000000
#define inf 0x3f3f3f3f
#define ls son[rt][0]
#define rs son[rt][1]
inline void read(int& x)
{
x=0;char c=getchar();int f=1;
while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=f;
}
inline int min(int x,int y)
{
return x<y?x:y;
}
struct fhqtreap
{
int rnd[maxn],siz[maxn],val[maxn],son[maxn][2],tot,root;
int x,y,z;
inline void update(int rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
}
void split(int rt,int k,int& x,int& y)
{
if(!rt)
{
x=y=0;
return;
}
if(val[rt]<=k) x=rt,split(rs,k,rs,y);
else y=rt,split(ls,k,x,ls);
update(rt);
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(rnd[x]<rnd[y])
{
son[x][1]=merge(son[x][1],y);
update(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
update(y);
return y;
}
}
inline void pop(int v)
{
split(root,v,x,z);
split(x,v-1,x,y);
y=merge(son[y][0],son[y][1]);
root=merge(merge(x,y),z);
}
inline int newnode(int v)
{
siz[++tot]=1;
val[tot]=v;
rnd[tot]=rand();
return tot;
}
inline void insert(int v)
{
split(root,v,x,y);
root=merge(merge(x,newnode(v)),y);
}
inline int getkth(int rt,int k)
{
while(true)
{
if(k<=siz[ls]) rt=ls;
else if(k==siz[ls]+1) return rt;
else k-=siz[ls]+1,rt=rs;
}
}
inline int getrank(int v)
{
split(root,v-1,x,y);
int ans=siz[x]+1;
root=merge(x,y);
return ans;
}
inline int lower(int v)
{
split(root,v-1,x,y);
int ans=val[getkth(x,siz[x])];
root=merge(x,y);
return ans;
}
inline int upper(int v)
{
split(root,v,x,y);
int ans=val[getkth(y,1)];
root=merge(x,y);
return ans;
}
inline bool find(int v)
{
return lower(v)==v;
}
inline bool empty()
{
return getrank(inf)==2;
}
}st[2];
inline int solve(int v,int op)
{
if(st[op^1].empty())
{
st[op].insert(v);
return 0;
}
int pre=st[op^1].lower(v),las=st[op^1].upper(v);
if(pre==-inf)
{
st[op^1].pop(las);
return las-v;
}
else if(las==inf)
{
st[op^1].pop(pre);
return v-pre;
}
else
{
if(las+pre<v+v)
{
st[op^1].pop(las);
return las-v;
}
else
{
st[op^1].pop(pre);
return v-pre;
}
}
}
int main()
{
srand(time(NULL));
int n,op,v;
long long ans=0;
read(n);
st[0].insert(inf),st[0].insert(-inf);
st[1].insert(inf),st[1].insert(-inf);
for(int i=1;i<=n;++i)
{
read(op),read(v);
ans+=solve(v,op);
}
printf("%lld\n",ans%P);
return 0;
}
F code
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000005
#define ls son[rt][0]
#define rs son[rt][1]
int rnd[maxn],val[maxn],son[maxn][2],siz[maxn],lazy[maxn];
int tot,root,x,y,z;
inline void read(int& x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
inline void update(int rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
}
inline void pushdown(int rt)
{
if(!lazy[rt]) return;
swap(ls,rs);
lazy[ls]^=1,lazy[rs]^=1;
lazy[rt]=0;
}
void split(int rt,int k,int& x,int& y)
{
if(!rt) x=y=0;
else
{
pushdown(rt);
if(k>siz[ls]) x=rt,split(rs,k-siz[ls]-1,rs,y);
else y=rt,split(ls,k,x,ls);
update(rt);
}
}
int merge(int x,int y)
{
if(!x||!y) return x|y;
if(rnd[x]<=rnd[y])
{
pushdown(x);
son[x][1]=merge(son[x][1],y);
update(x);
return x;
}
else
{
pushdown(y);
son[y][0]=merge(x,son[y][0]);
update(y);
return y;
}
}
inline int newnode(int v)
{
siz[++tot]=1;
val[tot]=v;
rnd[tot]=rand();
return tot;
}
inline void insert(int v)
{
split(root,v,x,y);
root=merge(merge(x,newnode(v)),y);
}
void print(int rt)
{
pushdown(rt);
if(ls) print(ls);
printf("%d ",val[rt]);
if(rs) print(rs);
}
int main()
{
srand((unsigned long long)new char);
int n,m,fr,to;
read(n);read(m);
for(int i=1;i<=n;++i) insert(i);
for(int i=1;i<=m;++i)
{
read(fr),read(to);
split(root,to,x,z);
split(x,fr-1,x,y);
lazy[y]^=1;
root=merge(merge(x,y),z);
}
print(root);
return 0;
}
G code
#include<bits/stdc++.h>
using namespace std;
#define ui unsigned int
#define rg register
#define maxn 100005
ui last,n,m,seed;
int root,tot,x,y,z;
int num[maxn*10],tim[maxn*10];
inline ui randnum()
{
seed=seed*17+last;
return seed%m+1;
}
struct Person
{
int num,tim;
};
template<typename T>
struct fhqTreap
{
#define ls son[rt][0]
#define rs son[rt][1]
T val[maxn];
int son[maxn][2],rnd[maxn],siz[maxn];
inline void update(rg int rt)
{
siz[rt]=siz[ls]+siz[rs]+1;
}
void split(rg int rt,rg T v,rg int& x,rg int& y)
{
if(!rt) x=y=0;
else
{
if(val[rt].num<v.num||(val[rt].num==v.num&&val[rt].tim>=v.tim))
y=rt,split(ls,v,x,ls);
else x=rt,split(rs,v,rs,y);
update(rt);
}
}
void split(rg int rt,rg int k,rg int& x,rg int& y)
{
if(!rt) x=y=0;
else
{
if(k<=siz[ls]) y=rt,split(ls,k,x,ls);
else x=rt,split(rs,k-siz[ls]-1,rs,y);
update(rt);
}
}
int merge(rg int x,rg int y)
{
if(!x||!y) return x|y;
if(rnd[x]<rnd[y])
{
son[x][1]=merge(son[x][1],y);
update(x);
return x;
}
else
{
son[y][0]=merge(x,son[y][0]);
update(y);
return y;
}
}
inline int newnode(rg T v)
{
val[++tot]=v;
rnd[tot]=rand();
siz[tot]=1;
return tot;
}
inline int getrank(rg T v)
{
split(root,v,x,y);
int ans=siz[x];
root=merge(x,y);
return ans;
}
#undef ls
#undef rs
};
fhqTreap<Person> st;
inline void write(rg int x)
{
if(x>=10) write(x/10);
putchar(x%10+'0');
}
int main()
{
//freopen("roll.in","r",stdin),freopen("roll.out","w",stdout);
int T;
scanf("%d",&T);
last=7;
while(T--)
{
scanf("%d%d%d",&m,&n,&seed);
root=tot=0;
memset(num,0,sizeof(num));
memset(tim,0,sizeof(tim));
memset(st.son,0,sizeof(st.son));
rg unsigned int ta,tb;
for(rg int i=1;i<=n;++i)
{
ta=randnum(),tb=randnum();
if(!num[ta])
{
++num[ta],tim[ta]+=tb;
rg int now=st.newnode((Person){num[ta],tim[ta]});
st.split(root,(Person){num[ta],tim[ta]},x,y);
root=st.merge(st.merge(x,now),y);
}
else
{
st.split(root,(Person){num[ta],tim[ta]},x,y);
st.split(y,1,y,z);
++st.val[y].num,st.val[y].tim+=tb;
++num[ta],tim[ta]+=tb;
root=st.merge(x,z);
st.split(root,st.val[y],x,z);
root=st.merge(st.merge(x,y),z);
}
write(last=st.getrank((Person){num[ta],tim[ta]}));
puts(" ");
}
}
return 0;
}
一切伟大的行动和思想,都有一个微不足道的开始。
There is a negligible beginning in all great action and thought.
There is a negligible beginning in all great action and thought.