本来是要做hihocoder 1034 毁灭者问题,发现朴素的数据结构无法满足该题目如此BT的要求,随查了一下,splay tree貌似可以解决,于是目标转到了学习splay tree上。
学习splay tree 的主要参考资料:
《伸展树的基本操作与应用》– 杨思雨
《运用伸展树解决数列维护问题》– By Crash
《Splaying a Search Tree in Preorder Takes Linear Time》
《NOI 2005 维护数列》– ByVoid
《NOI 2005 维护数列 测试数据》
太晚了,具体操作原理、细节明天再更新。。
这里先发一个poj3468 A Simple Problem with Integers AC代码,当做初学splay tree的第一道测试题。
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
#define ll64 long long int
struct st{
struct node{
long long int size,value,cover,sums;
struct node *pre,*ch[2];
};
node *nill,*root;
node buf[200000]; int bufsize;
int pushdown(node *x){
if(x==nill || x==NULL) return 0;
if(x->cover){
x->value+=x->cover; x->sums+=x->cover*x->size;
x->ch[0]->cover+=x->cover;
x->ch[1]->cover+=x->cover;
x->cover=0;
}
return 0;
}
int update(node *x){
if(x==nill || x==NULL) return 0;
pushdown(x->ch[0]);pushdown(x->ch[1]);
x->size = x->ch[0]->size+x->ch[1]->size+1;
x->sums=x->ch[0]->sums+x->ch[1]->sums+x->value;
return 0;
}
node *getnode(ll64 value,node *fa){
node *p=buf+bufsize++;
p->cover=0;
p->value=p->sums=value;
p->size=1;
p->ch[0]=p->ch[1]=nill; p->pre=fa;
return p;
}
int init(){
bufsize=0; nill=root=NULL;
nill=getnode(0,NULL);
nill->size=0; nill->ch[0]=nill->ch[1]=NULL;
root=getnode(0,nill);
root->ch[1]=getnode(0,root);
return 0;
}
int rotateto(node*x,int to){
node *y=x->pre;
y->ch[to^1]=x->ch[to];
y->ch[to^1]->pre=y;
x->pre=y->pre;
if(y==y->pre->ch[0])x->pre->ch[0]=x;
else x->pre->ch[1]=x;
x->ch[to]=y; y->pre=x;
update(y);
if(y==root) root=x;
return 0;
}
int splay(node *x,node *fa){
pushdown(x);
while(x->pre!=fa ){
if(x->pre->pre==fa){
if(x->pre->ch[0]==x) rotateto(x,1);
else rotateto(x,0);
}else{
if(x->pre->pre->ch[0]==x->pre){
if(x->pre->ch[0]==x){rotateto(x->pre,1);rotateto(x,1);}
else{rotateto(x,0);rotateto(x,1);}
}else{
if(x->pre->ch[0]==x){rotateto(x,1);rotateto(x,0);}
else{rotateto(x->pre,0);rotateto(x,0);}
}
}
}
update(x);
return 0;
}
int select(int k,node *fa){
node *rt=root;
while(rt!=nill){
pushdown(rt);
if(rt->ch[0]->size == k-1) break;
else if(rt->ch[0]->size>k-1) rt=rt->ch[0];
else {k-=rt->ch[0]->size+1; rt=rt->ch[1];}
}
splay(rt,fa);
return 0;
}
int insert(int pos,int tot){
node *p,*q;
long long int s;
scanf("%lld",&s);
p=q=getnode(s,nill);
for(int i=1;i<tot;i++){
scanf("%lld",&s);
p=p->ch[1]=getnode(s,p);
}
select(pos+1,nill);
select(pos+2,root);
root->ch[1]->ch[0]=q; q->pre=root->ch[1];
splay(p,nill);
return 0;
}
int add(int a,int b,long long int c){
select(a,nill);
select(b+2,root);
root->ch[1]->ch[0]->cover+=c;
splay(root->ch[1]->ch[0],nill);
return 0;
}
ll64 getsums(int a,int b){
select(a,nill);
select(b+2,root);
// cout<<root->value<<" "<<root->ch[1]->value<<endl;
pushdown(root->ch[1]->ch[0]);
return root->ch[1]->ch[0]->sums;
}
};
int main(){
int n,q;
scanf("%d %d",&n,&q);
st *str=new st;
str->init();
str->insert(0,n);
char s[10]; ll64 c;
int a,b;
for(int i=0;i<q;i++){
scanf("%s %d %d",s,&a,&b);
//cout<<s<<" "<<a<<" "<<b<<endl;
if(s[0]=='Q'){
printf("%lld\n",str->getsums(a,b));
}else{
scanf("%lld",&c);
str->add(a,b,c);
}
}
return 0;
}
同时还查到了一个有意思的问题,在这里记下:
《动态树问题及其应用》
扫码关注作者,定期分享技术、算法类文章