平衡树之伸展树(Splay Tree)题目整理
前言
学习于yyb
本来是想写个算法解释,克自己写了一半总感觉像复制的,各位就去yyb哪里学吧
这里附上几个BZOJ的模板题
\n
\n
\n
\n
练习1 BZOJ 3224 普通平衡树
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作
splay的模板题
也就是splay的全部操作
前言的博客讲的很详尽了
/**************************************************************
Problem: 3224
User: 3010651817
Language: C++
Result: Accepted
Time:500 ms
Memory:10672 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#define maxN 400007
using namespace std;
inline int read() {
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
int root,tot;
struct Node {
int ch[2],val,ff,size,cnt;
}t[maxN];
inline void pushup(int u) {
t[u].size=t[t[u].ch[0]].size+t[t[u].ch[1]].size+t[u].cnt;
}
inline void rotate(int x) { //核心操作->旋转
int y=t[x].ff,z=t[y].ff,k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x;//爷爷和儿子
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];//爸爸和孙子
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;//爸爸和儿子
pushup(y);
pushup(x);
}
inline void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
void find(int x) {
int u=root;
if(!u) return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
splay(u,0);
}
inline void insert(int x) {
int u=root,ff=0;
while(u&&t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u)t[u].cnt++;
else {
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[tot].ff=ff;
t[tot].val=x;
t[tot].cnt=1;
t[tot].size=1;
}
splay(u,0);
}
int Next(int x,int f) {
find(x);
int u=root;
if(t[u].val>x&&f) return u;
if(t[u].val<x&&!f) return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
void Delete(int x) {
int last=Next(x,0);
int nxt=Next(x,1);
splay(last,0);
splay(nxt,last);
int del=t[nxt].ch[0];
if(t[del].cnt>1) t[del].cnt--,splay(del,0);
else t[nxt].ch[0]=0;
}
int k_th(int x) {
int u=root;
if(t[u].size<x) return 0;
while(1) {
int y=t[u].ch[0];
if(x>t[y].size+t[u].cnt) {
x-=t[y].size+t[u].cnt;
u=t[u].ch[1];
} else {
if(t[y].size>=x)
u=y;
else
return t[u].val;
}
}
}
int main()
{
int n=read();
insert(0x7fffffff);
insert(-0x7fffffff);
while(n--)
{
int opt=read(),x=read();
if(opt==1) insert(x);else
if(opt==2) Delete(x);else
if(opt==3) find(x),printf("%d\n",t[t[root].ch[0]].size);else
if(opt==4) printf("%d\n",k_th(x+1));else
if(opt==5) printf("%d\n",t[Next(x,0)].val);else
if(opt==6) printf("%d\n",t[Next(x,1)].val);
}
return 0;
}
练习2 BZOJ 3223 文艺平衡树
维护一个要m次区间翻转的区间,最后输出
看题目一开始我还以为这是比普通的平衡树厉害的题目,但其实比普通的还简单的一个题
区间翻转,只要范围内的左右节点全部互换就可以了
这就可以类似于线段树的懒惰标记(原来splay也可以pushdown啊)
建树的话,由于区间大小不变
懒得直接套insert
也可以写个build
/**************************************************************
Problem: 3223
User: 3010651817
Language: C++
Result: Accepted
Time:2288 ms
Memory:14968 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#define maxN 500007
using namespace std;
inline int read() {
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
int root,tot;
struct Node {
int ch[2],val,ff,size,cnt;
int lazy;
}t[maxN];
inline void pushup(int u) {
t[u].size=t[t[u].ch[0]].size+t[t[u].ch[1]].size+1;
}
void pushdown(int x)
{
if(t[x].lazy)
{
t[t[x].ch[0]].lazy^=1;
t[t[x].ch[1]].lazy^=1;
t[x].lazy=0;
swap(t[x].ch[0],t[x].ch[1]);
}
}
inline void rotate(int x) { //核心操作->旋转
int y=t[x].ff,z=t[y].ff,k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x;//爷爷和儿子
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];//爸爸和孙子
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;//爸爸和儿子
pushup(x);
pushup(y);
}
inline void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
inline void insert(int x) {
int u=root,ff=0;
while(u&&t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[tot].ff=ff;
t[tot].val=x;
t[tot].cnt=1;
t[tot].size=1;
splay(u,0);
}
int k_th(int x) {
int u=root;
while(1) {
pushdown(u);
int y=t[u].ch[0];
if(x>t[y].size+t[u].cnt) {
x-=t[y].size+t[u].cnt;
u=t[u].ch[1];
} else {
if(t[y].size>=x)
u=y;
else
return t[u].val;
}
}
}
int n;
inline void write(int x)
{
pushdown(x);
if(t[x].ch[0])write(t[x].ch[0]);
if(t[x].val>1&&t[x].val<n+2)printf("%d ",t[x].val-1);
if(t[x].ch[1])write(t[x].ch[1]);
}
void work(int x,int y)
{
int l=k_th(x);
int r=k_th(y+2);
splay(l,0);
splay(r,l);
t[t[t[root].ch[1]].ch[0]].lazy^=1;
}
int main()
{
n=read();
int m=read();
for(int i=1;i<=n+2;++i) insert(i);
while(m--)
{
int x=read(),y=read();
work(x,y);
}
write(root);
puts("");
return 0;
}
练习3 BZOJ 1588 [HNOI2002]营业额统计
求\(\sum_{1}^{n}\)最小波动值
最小波动值=min{|该天以前某一天的营业额-该天营业额|}。
很明显,最小波动值就是|该天营业额-他的前驱(<=)|
或者|该天营业额-他的后继(>=)|
两者取min就可以
/**************************************************************
Problem: 1588
User: 3010651817
Language: C++
Result: Accepted
Time:232 ms
Memory:5048 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#define maxN 160007
using namespace std;
inline int read() {
int x=0,f=1;char s=getchar();
while(s<'0'||s>'9') {if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9') {x=x*10+s-'0';s=getchar();}
return x*f;
}
inline int abs(int a) {
return a>0 ? a : -a;
}
int root,tot;
struct Node {
int ch[2],val,ff,size,cnt;
}t[maxN];
inline void pushup(int u) {
t[u].size=t[t[u].ch[0]].size+t[t[u].ch[1]].size+t[u].cnt;
}
inline void rotate(int x) { //核心操作->旋转
int y=t[x].ff,z=t[y].ff,k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x;//爷爷和儿子
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];//爸爸和孙子
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;//爸爸和儿子
pushup(x);
pushup(y);
}
inline void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
void find(int x) {
int u=root;
if(!u) return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
splay(u,0);
}
inline void insert(int x) {
int u=root,ff=0;
while(u&&t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u)t[u].cnt++;
else {
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[tot].ff=ff;
t[tot].val=x;
t[tot].cnt=1;
t[tot].size=1;
}
splay(u,0);
}
int Next(int x,int f) {
int u=root;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
if(x==t[u].val) return u;
splay(u,0);
u=root;
if(t[u].val>x&&f) return u;
if(t[u].val<x&&!f) return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
int main()
{
//freopen("a.in","r",stdin);
int n=read();
insert(0x7fffffff);
insert(-0x7fffffff);
int tot=0;
int x=read();
int dsr=x;
insert(x);
tot+=x;
x=read();
insert(x);
tot+=abs(x-dsr);
for(int i=3;i<=n;++i)
{
x=read();
int tmp1=t[Next(x,0)].val;
int tmp2=t[Next(x,1)].val;
insert(x);
int ans=0x3f3f3f3f;
if(tmp1!=-0x7fffffff)
ans=min(ans,abs(tmp1-x));
if(tmp2!=0x7fffffff)
ans=min(ans,abs(tmp2-x));
tot+=ans;
//cout<<ans<<"\n";
}
printf("%d",tot);
return 0;
}
练习4 BZOJ 1208 [HNOI2004]宠物收养场
题目
一开始读错了题(郝志章)
很明显,题目想让你建两棵splay(s),但是
如果一开始宠物多,领养者少,过渡到到宠物少,领养者多的情况的时候,一定会出现树上为空的情况,所以我们就只是用一颗树就可以了
/**************************************************************
Problem: 1208
User: 3010651817
Language: C++
Result: Accepted
Time:208 ms
Memory:8800 kb
****************************************************************/
#include <cstdio>
#include <iostream>
#define mod 1000000
#define inf 0x7fffffff
#define maxN 320007
using namespace std;
int n;
int tot_pet,tot_adopter;
inline int min(int a,int b) {
return a>b?b:a;
}
inline int abs(int a) {
return a>0?a:-a;
}
inline int read() {
int x=0,f=1;
char s=getchar();
while(s<'0'||s>'9') {
if(s=='-')f=-1;
s=getchar();
}
while('0'<=s&&s<='9') {
x=x*10+s-'0';
s=getchar();
}
return x*f;
}
int root,tot;
struct Node {
int ch[2],val,ff,size,cnt;
} t[maxN];
inline void pushup(int u) {
t[u].size=t[t[u].ch[0]].size+t[t[u].ch[1]].size+t[u].cnt;
}
inline void rotate(int x) {
int y=t[x].ff,z=t[y].ff,k=(t[y].ch[1]==x);
t[z].ch[t[z].ch[1]==y]=x;
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;
pushup(x);
pushup(y);
}
inline void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
void find(int x) {
int u=root;
if(!u) return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
splay(u,0);
}
inline void insert(int x) {
int u=root,ff=0;
while(u&&t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u)t[u].cnt++;
else {
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[tot].ff=ff;
t[tot].val=x;
t[tot].cnt=1;
t[tot].size=1;
}
splay(u,0);
}
int Next(int x,int f) {
find(x);
int u=root;
if(t[u].val>x&&f) return u;
if(t[u].val<x&&!f) return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
void Delete(int x) {
int last=Next(x,0);
int nxt=Next(x,1);
splay(last,0);
splay(nxt,last);
int del=t[nxt].ch[0];
if(t[del].cnt>1) t[del].cnt--,splay(del,0);
else t[nxt].ch[0]=0;
}
inline int check(int x) {
int u=root;
if(!u) return -1;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
if(x==t[u].val) return u;
return -1;
}
//维护一颗splay就可以
//如果一开始宠物多,人少,之后如果宠物少,人多的话 ,splay树必须先为空
//这样就可以重复利用了
int main() {
n=read();
insert(inf);
insert(-inf);
int tot=0;
while(n--) {
int a=read(),b=read();
if(a) { //adopter
if(tot_pet) { //还有宠物
tot_pet--;
int zz=check(b);
if(zz!=-1) {
Delete(t[zz].val);
continue;
}//检查一下有没有前面等于自己的宠物
int ans=inf;
int tmp1=Next(b,0);//前驱,注意是标号!!!
int tmp2=Next(b,1);//后继
//cout<<t[tmp1].val<<" "<<t[tmp2].val<<"\n";
if(t[tmp1].val==-inf) {//没有前驱
tot+=abs(b-t[tmp2].val);
tot%=mod;
Delete(t[tmp2].val);
//continue;
} else if(t[tmp2].val==inf) { //没有后缀
tot+=abs(b-t[tmp1].val);
tot%=mod;
Delete(t[tmp1].val);
//continue;
} else if(abs(b-t[tmp1].val) > abs(b-t[tmp2].val)) {
tot+=abs(b-t[tmp2].val);
tot%=mod;
Delete(t[tmp2].val);
} else {
tot+=abs(b-t[tmp1].val);
tot%=mod;
Delete(t[tmp1].val);
}
} else {
insert(b);
tot_adopter++;
}
} else { //pet
if(tot_adopter) { //还有领养者
tot_adopter--;
int zz=check(b);
if(zz!=-1) {
Delete(t[zz].val);
continue;
}//检查一下有没有前面等于自己的宠物
int ans=inf;
int tmp1=Next(b,0);//前驱,注意是标号!!!
int tmp2=Next(b,1);//后继
//cout<<t[tmp1].val<<" "<<t[tmp2].val<<"\n";
if(t[tmp1].val==-inf) {//没有前驱
tot+=abs(b-t[tmp2].val);
tot%=mod;
Delete(t[tmp2].val);
continue;
}
if(t[tmp2].val==inf) {//没有后缀
tot+=abs(b-t[tmp1].val);
tot%=mod;
Delete(t[tmp1].val);
continue;
}
if(abs(b-t[tmp1].val) > abs(b-t[tmp2].val)) {
tot+=abs(b-t[tmp2].val);
tot%=mod;
Delete(t[tmp2].val);
} else {
tot+=abs(b-t[tmp1].val);
tot%=mod;
Delete(t[tmp1].val);
}
} else { //adopter空了
insert(b);
tot_pet++;
}
}
}
printf("%d\n",tot);
return 0;
}
练习5 BZOJ 1507 [NOI2003]文本编辑器 editor
题目
注意:luogu的朋友,输入需要注意\r
输出的话,把l到r的子树旋到root右儿子的左儿子上,然后中序遍历
删除l到r的子树的子树,旋转和输出类似
感兴趣的朋友还可以看看
BZOJ 1269(非重题) [AHOI2006]文本编辑器editor
这个
/**************************************************************
Problem: 1507
User: 3010651817
Language: C++
Result: Accepted
Time:2128 ms
Memory:54028 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#define maxn 3000001
using namespace std;
int read()
{
int x=0,f=1;char s=getchar();
while('0'>s||s>'9'){
if(s=='-')f=-1;
s=getchar();
}
while('0'<=s&&s<='9') {
x=x*10+s-'0';
s=getchar();
}
return x*f;
}
int n,cnt,root,mouse;
int fa[maxn],ch[maxn][2],siz[maxn];
char w[maxn];
void update(int x) {
siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
int get(int x) {
return ch[fa[x]][1]==x;
}
void rotate(int x) {
int f=fa[x],ff=fa[f],son=get(x);
ch[f][son]=ch[x][son^1];
if(ch[f][son]) fa[ch[f][son]]=f;
fa[f]=x;
ch[x][son^1]=f;
fa[x]=ff;
if(ff) ch[ff][ch[ff][1]==f]=x;
update(f);
update(x);
}
void splay(int x,int to) {
if(x==to||fa[x]==to) return;
if(to==0) root=x;
for(int f; (f=fa[x])&&(f!=to); rotate(x)) {
if(fa[f]!=to)
rotate(get(x)==get(f)?f:x);
}
update(x);
}
int rank(int x,int pos) {
if(siz[ch[pos][0]]+1==x) {
splay(pos,0);
return pos;
}
if(siz[ch[pos][0]]>=x) return rank(x,ch[pos][0]);
else return rank(x-siz[ch[pos][0]]-1,ch[pos][1]);
}
char s[maxn];
int build(int l,int r,int f) {
if(l>r) return 0;
int mid=(l+r)>>1,cur=++cnt;
fa[cur]=f;
w[cur]=s[mid];
ch[cur][0]=build(l,mid-1,cur);
ch[cur][1]=build(mid+1,r,cur);
update(cur);
return cur;
}
void insert(int l,int len) {
int x=rank(l,root),y=rank(l+1,root);
splay(x,0);
splay(y,root);
ch[y][0]=build(1,len,y);
update(y);
update(x);
}
void del(int l,int r) {
int x=rank(l,root),y=rank(r+2,root);
splay(x,0);
splay(y,root);
ch[y][0]=0;
update(y);
update(x);
}
void dfs(int x) {
if(!x) return ;
dfs(ch[x][0]);
printf("%c",w[x]);
dfs(ch[x][1]);
}
void print(int l,int len) {
int x=rank(l,root),y=rank(l+len+1,root);
splay(x,0);
splay(y,root);
dfs(ch[y][0]);
puts("");
}
int main() {
int i,j,t1;
char op[10];
char c;
n=read();
root=++cnt;
w[cnt]=0;
siz[cnt]=2;
ch[cnt][1]=cnt+1;
cnt++;
fa[cnt]=cnt-1;
w[cnt]=0;
siz[cnt]=1;
mouse=1;
for(i=1; i<=n; i++) {
scanf("%s",op);
if(op[0]=='I') {
t1=read();
for(j=1; j<=t1; j++) {
c=getchar();
while(c=='\n'||c=='\r') c=getchar();//超级大坑
s[j]=c;
}
insert(mouse,t1);
}
if(op[0]=='D') {
t1=read();
del(mouse,mouse+t1-1);
}
if(op[0]=='G') {
t1=read();
print(mouse,t1);
}
if(op[0]=='M') {
t1=read();
mouse=t1+1;
}
if(op[0]=='N') mouse++;
if(op[0]=='P') mouse--;
}
}
练习6 BZOJ 1503 [NOI2004]郁闷的出纳员
题目
由于是全体降工资,涨工资,所以不用lazy,不用改树
直接把标准改一下就,但加入新人的时候,也需要把它的工资改一下。
(标准都改,新人也需要同步)
然后降工资的时候删除一下标准的1到标准前缀的子树就可以了
这里查询第k多工资,而不是第k小,所以需要 员工总数-k+1
/**************************************************************
Problem: 1503
User: 3010651817
Language: C++
Result: Accepted
Time:784 ms
Memory:3872 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#define INF 0x3f3f3f3f
#define maxn 110000
using namespace std;
int n,root;
struct Node {
int ch[2];
int val;
int ff;
int cnt;
int size;
} t[maxn];
int tot,mm,ans,add;
inline void pushup(int x) {
t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
}
inline void rotate(int x) {
int y=t[x].ff,z=t[y].ff,k=(x==t[y].ch[1]);
t[z].ch[y==t[z].ch[1]]=x;
t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];
t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;
t[y].ff=x;
pushup(y);
pushup(x);
}
inline void splay(int x,int goal) {
while(t[x].ff!=goal) {
int y=t[x].ff;
int z=t[y].ff;
if(z!=goal)
(t[z].ch[0]==y)^(t[y].ch[0]==x)? rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
void find(int x) {
int u=root;
if(!u) return;
while(t[u].ch[x>t[u].val]&&x!=t[u].val)
u=t[u].ch[x>t[u].val];
splay(u,0);
}
inline void insert(int x) {
int u=root,ff=0;
while(u&&t[u].val!=x) {
ff=u;
u=t[u].ch[x>t[u].val];
}
if(u)t[u].cnt++;
else {
u=++tot;
if(ff)
t[ff].ch[x>t[ff].val]=u;
t[u].ch[0]=t[u].ch[1]=0;
t[tot].ff=ff;
t[tot].val=x;
t[tot].cnt=1;
t[tot].size=1;
}
splay(u,0);
}
inline int Next(int x,int f) {
find(x);
int u=root;
if(t[u].val>=x&&f)return u;
if(t[u].val<=x&&!f)return u;
u=t[u].ch[f];
while(t[u].ch[f^1])u=t[u].ch[f^1];
return u;
}
int k_th(int x) {
int u=root;
if(t[u].size<x||x<1) return -INF;
while(1) {
int y=t[u].ch[0];
if(x>t[y].size+t[u].cnt) {
x-=t[y].size+t[u].cnt;
u=t[u].ch[1];
} else {
if(t[y].size>=x)
u=y;
else
return t[u].val;
}
}
}
int main() {
insert(+INF);
scanf("%d%d",&n,&mm);
int peo=0;
while(n--) {
int x;
char ch[3];
scanf("%s%d",ch,&x);
if(ch[0]=='I') {
if(x>=mm) {
insert(x-add);
peo++;
}
}
if(ch[0]=='A')
add+=x;
if(ch[0]=='S') {
add-=x;
int gg=Next(mm-add,1);
splay(gg,0);
ans+=t[t[root].ch[0]].size;
peo-=t[t[root].ch[0]].size;
t[t[root].ch[0]].size=t[t[root].ch[0]].cnt=0;
t[root].ch[0]=0;
t[0].size=0;
pushup(root);
}
if(ch[0]=='F') {
int gg=k_th(peo-x+1);
printf("%d\n",gg==-INF?-1:(gg+add));
}
}
printf("%d\n",ans);
return 0;
}
/*
思路一样,可惜自己D了2小时没弄出来╮(╯_╰)╭太弱了
*/
平衡树之伸展树(Splay Tree)题目整理的更多相关文章
- 纸上谈兵: 伸展树 (splay tree)[转]
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 我们讨论过,树的搜索效率与树的深度有关.二叉搜索树的深度可能为n,这种情况下,每 ...
- 树-伸展树(Splay Tree)
伸展树概念 伸展树(Splay Tree)是一种二叉排序树,它能在O(log n)内完成插入.查找和删除操作.它由Daniel Sleator和Robert Tarjan创造. (01) 伸展树属于二 ...
- K:伸展树(splay tree)
伸展树(Splay Tree),也叫分裂树,是一种二叉排序树,它能在O(lgN)内完成插入.查找和删除操作.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使 ...
- 高级搜索树-伸展树(Splay Tree)
目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...
- 【BBST 之伸展树 (Splay Tree)】
最近“hiho一下”出了平衡树专题,这周的Splay一直出现RE,应该删除操作指针没处理好,还没找出原因. 不过其他操作运行正常,尝试用它写了一道之前用set做的平衡树的题http://codefor ...
- 伸展树(Splay tree)的基本操作与应用
伸展树的基本操作与应用 [伸展树的基本操作] 伸展树是二叉查找树的一种改进,与二叉查找树一样,伸展树也具有有序性.即伸展树中的每一个节点 x 都满足:该节点左子树中的每一个元素都小于 x,而其右子树中 ...
- 伸展树 Splay Tree
Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...
- HDU 4453 Looploop (伸展树splay tree)
Looploop Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- hdu 2871 Memory Control(伸展树splay tree)
hdu 2871 Memory Control 题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出 ...
- [Splay伸展树]splay树入门级教程
首先声明,本教程的对象是完全没有接触过splay的OIer,大牛请右上角.. 首先引入一下splay的概念,他的中文名是伸展树,意思差不多就是可以随意翻转的二叉树 PS:百度百科中伸展树读作:BoGa ...
随机推荐
- linux中使用arcpy
切换到对应目录 即下图的 server安装路径 /home/arcgis/arcgis/server/tools 然后输入 ./python (这一步要注意 python这个命令 ...
- java动态加载
先贴个笔记,后续用得着再深究. package test; import java.io.File; import java.io.IOException; import java.lang.refl ...
- python-面向对象-11-异常
异常 目标 异常的概念 捕获异常 异常的传递 抛出异常 01. 异常的概念 程序在运行时,如果 Python 解释器 遇到 到一个错误,会停止程序的执行,并且提示一些错误信息,这就是 异常 程序停止执 ...
- (3.13)mysql基础深入——mysql日志分析工具之mysqlsla【待完善】
(3.13)mysql基础深入——mysql 日志分析工具之mysqlsla 关键字:Mysql日志分析工具.mysqlsla 常用工具 [1]mysqldumpslow:官方提供的慢查询日志分析工具 ...
- [py]flask从0到1-模板/增删改查
flask知识点 1.后端渲染html到前端 render_template 2.后端获取前端数据 request.args.get 3.前端获取后端数据 模板 4.警示消息 flash {{ get ...
- <span> 标签
<span> 标签被用来组合文档中的行内元素. 如果不对 span 应用样式,那么 span 元素中的文本 与 其他文本不会有任何视觉上的差异.尽管如此,上例中的 span 元素仍然为 p ...
- Directed Graph Loop detection and if not have, path to print all path.
这里总结针对一个并不一定所有点都连通的general directed graph, 去判断graph里面是否有loop存在, 收到启发是因为做了[LeetCode] 207 Course Sched ...
- VS2010/MFC编程入门之四十二(MFC常用类:CString类)
上一节鸡啄米讲了分割窗口的有关知识,本节开始讲解MFC的一些常用类,先来说说CString类. CString类简介 CString类作为MFC的常用类,当之无愧.可以这样说,只要是从事MFC开发,基 ...
- SpringMVC+Spring+Mybatis+Maven+mysql整合
一.准备工作1.工具:jdk1.7.0_80(64)+tomcat7.0.68+myeclipse10.6+mysql-5.5.48-win322. 开发环境安装配置.Maven项目创建(参考:htt ...
- python 元组 序列上使用enumerate()函数
不能直接for n,x,y in enumerate(data)