注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

fanhq666的博客

Fan-Fun

 
 
 

日志

 
 

挖掘Treap的潜力  

2011-01-21 22:59:33|  分类: 程序 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
你的Treap能支持以下操作吗?
1.区间增减
2.区间求最小
3.区间反转(倒序)
4.区间移动(把一段剪切、粘贴)
不能?只能用splay?

其实,Treap也可以办到。
方法就是:设计把一个子树split成两个子树的算法,以及把两个子树merge的算法。

例:poj3580,代码见最后

另外一个应用:可持久化Treap
设计一个数据结构维护一个序列
 插入一个元素
 删除一个元素
 移动连续的一段(就是剪切、粘贴)
 *查询m次操作之前的第p个元素是谁
例:超级文本编辑器(我正在构思的一道题)
文本长度不超过100000
每次可以插入、删除、剪切粘贴
要求在线算法
每个操作10微秒时限,一共32M内存

这个可以参见算法导论,核心思想是:一个节点创建之后就不再删除。另外用垃圾回收。

poj3580
#include <cstdio>
#include <algorithm>
using namespace std;
int ran(){
static int x=1364684679;
x+=(x<<2)+1;
return x;
}
struct node{
int k,mn,delta,mark,w,sz;
node *l,*r;
static node* getnew(node *w=NULL){
static node *list=NULL;
if (w){
w->r=list;list=w;
return NULL;
}
if (!list){
node *q=new node[10000];
for (int i=0;i<10000;i++){
q[i].w=ran();
q[i].r=list;list=q+i;
}
}
node *p=list;list=list->r;
p->l=p->r=NULL;p->delta=p->mark=0;
return p;
}
void down(){
if (mark){
if (l)swap(l->l,l->r),l->mark^=1;
if (r)swap(r->l,r->r),r->mark^=1;
mark=0;
}
if (delta){
if (l)l->mn+=delta,l->delta+=delta,l->k+=delta;
if (r)r->mn+=delta,r->delta+=delta,r->k+=delta;
delta=0;
}
}
void update(){
mn=k;
if (l && mn>l->mn+delta)mn=l->mn+delta;
if (r && mn>r->mn+delta)mn=r->mn+delta;
sz=1;
if (l)sz+=l->sz;
if (r)sz+=r->sz;
}
};
#define SIZE(_) ((_)?(_)->sz:0)
struct Treap{
node *root;
Treap(){root=NULL;}
void ins(node *&p,int a,int k){
if (!p){
p=node::getnew();
p->k=p->mn=k;p->sz=1;
}else{
p->down();
if (SIZE(p->l)>=a){
ins(p->l,a,k);
node *q=p->l;
if (q->w<p->w){
q->down();
p->l=q->r;q->r=p;p=q;
p->r->update();
}
}else{
ins(p->r,a-SIZE(p->l)-1,k);
node *q=p->r;
if (q->w<p->w){
q->down();
p->r=q->l;q->l=p;p=q;
p->l->update();
}
}
p->update();
}
}
void ins(int a,int k){ins(root,a,k);}
static void merge(node *&p,node *x,node *y){
if (!x || !y){
p=x?x:y;
}else if (x->w<y->w){
x->down();
merge(x->r,x->r,y);
x->update();
p=x;
}else{
y->down();
merge(y->l,x,y->l);
y->update();
p=y;
}
}
void del(node *&p,int a){
p->down();
if (SIZE(p->l)==a){
node *q=p;
merge(p,p->l,p->r);
node::getnew(q);
}else if (SIZE(p->l)>a){
del(p->l,a);
p->update();
}else{
del(p->r,a-SIZE(p->l)-1);
p->update();
}
}
void del(int a){del(root,a);}
static void cut(node *p,node *&x,node *&y,int a){
if (a==0){
x=NULL;y=p;
}else if (a==SIZE(p)){
x=p;y=NULL;
}else{
p->down();
if (SIZE(p->l)>=a){
y=p;
cut(p->l,x,y->l,a);
y->update();
}else{
x=p;
cut(p->r,x->r,y,a-SIZE(p->l)-1);
x->update();
}
}
}
int ask(node *p,int a,int b){
if (a==0 && b==SIZE(p)-1)return p->mn;
p->down();
int u=SIZE(p->l);
int r=(a<=u && u<=b?p->k:~0u>>1);
if (a<u)r=min(r,ask(p->l,a,b>=u?u-1:b));
if (b>u)r=min(r,ask(p->r,a<=u?0:a-u-1,b-u-1));
return r;
}
int ask(int a,int b){return ask(root,a,b);}
void dfs(node *p,int lv){
if (p){
dfs(p->l,lv+1);
for (int i=0;i<lv;i++)putchar(' '),putchar(' ');
printf("%d %d %d %d %d\n",p->k,p->sz,p->mn,p->delta,p->mark);
dfs(p->r,lv+1);
}
}
void dfs(){dfs(root,0);puts("");}
}T;
void Ins(int a,int k){
//printf("ins %d %d\n",a,k);
T.ins(a,k);
}
void Del(int a){
//printf("del %d\n",a);
T.del(a);
}
void Revolve(int a,int b,int c){
//printf("revolve %d %d %d\n",a,b,c);
node *p,*q,*r,*s;
Treap::cut(T.root,p,q,a);
Treap::cut(q,q,r,b-a+1);
Treap::cut(r,r,s,c-b);
Treap::merge(p,p,r);
Treap::merge(p,p,q);
Treap::merge(T.root,p,s);
}
void Reverse(int a,int b){
//printf("reverse %d %d\n",a,b);
node *p,*q,*r;
Treap::cut(T.root,p,q,a);
Treap::cut(q,q,r,b-a+1);
q->mark^=1;swap(q->l,q->r);
Treap::merge(p,p,q);
Treap::merge(T.root,p,r);
}
void Add(int a,int b,int c){
//printf("add %d %d %d\n",a,b,c);
node *p,*q,*r;
Treap::cut(T.root,p,q,a);
Treap::cut(q,q,r,b-a+1);
//T.dfs(q,0);puts("");
q->k+=c;q->mn+=c;q->delta+=c;
//printf("c=%d\n",c);
//T.dfs(q,0);
//puts("");
Treap::merge(p,p,q);
Treap::merge(T.root,p,r);
}
int Ask(int a,int b){
//printf("ask %d %d\n",a,b);
return T.ask(a,b);
}
int main()
{
int N;
scanf("%d",&N);
for (int i=0;i<N;i++){
int x;
scanf("%d",&x);
Ins(i,x);
}
int M;
//T.dfs();
scanf("%d",&M);
char buf[100];
while (M--){
scanf("%s",buf);
if (buf[0]=='A'){
int x,y,d;
scanf("%d%d%d",&x,&y,&d);x--;y--;
Add(x,y,d);
//T.dfs();
}else if (buf[0]=='I'){
int x,y;
scanf("%d%d",&x,&y);
Ins(x,y);
}else if (buf[0]=='D'){
int x;
scanf("%d",&x);x--;
Del(x);
}else if (buf[0]=='M'){
int x,y;
scanf("%d%d",&x,&y);x--;y--;
printf("%d\n",Ask(x,y));
}else if (buf[3]=='E'){
int x,y;
scanf("%d%d",&x,&y);x--;y--;
Reverse(x,y);
}else{
int x,y,t;
scanf("%d%d%d",&x,&y,&t);x--;y--;
t%=(y-x+1);
t+=(y-x+1);
t%=(y-x+1);
if (t){
Revolve(x,y-t,y);
}
}
}
return 0;
}

文本编辑器
#include <cstdio>
#include <bits/stl_pair.h>
#include <queue>
#include <deque>
#include <algorithm>
using namespace std;
int ran(){
static int x=222313214;
x+=(x<<2)+1;
return x;
}
struct node{
int w,sz;
char k;
node *l,*r;
static node* getnew(node *p=NULL){
static node * list=NULL;
if (p){
p->w=ran();
p->r=list;list=p;
return NULL;
}
if (!list){
node *p=new node[10000];
for (int i=0;i<10000;i++){
p[i].r=list;list=p+i;
p[i].w=ran();
}
}
node *q=list;
list=list->r;
q->l=NULL;q->r=NULL;q->sz=1;
return q;
}
};
#define SIZE(_) ((_)?(_)->sz:0)
int M,curid;
queue<pair<int,node*> > Literbox;
deque<node*> Roots;
void giveback(node *p){
Literbox.push(make_pair(curid,p));
}
void dfs(node *p,int a,int b){
if (p){
int u=SIZE(p->l);
if (u>a)dfs(p->l,a,min(b,u-1));
if (a<=u && u<=b)putchar(p->k);
if (b>u)dfs(p->r,max(a-u-1,0),b-u-1);
}
}
node * combine(node *p,node *q){
if (!p || !q)return p?p:q;
if (p->w<q->w){
node *a=node::getnew();
a->k=p->k;
a->w=p->w;
a->sz=p->sz+q->sz;
a->l=p->l;
a->r=combine(p->r,q);
giveback(p);
return a;
}else{
node *a=node::getnew();
a->k=q->k;
a->w=q->w;
a->sz=p->sz+q->sz;
a->r=q->r;
a->l=combine(p,q->l);
giveback(q);
return a;
}
}
void cutdown(node *p,node *&x,node *&y,int a){
if (a==0)x=NULL,y=p;
else if (a==SIZE(p)){
x=p;y=NULL;
}else{
if (SIZE(p->l)+1<=a){
x=node::getnew();
x->k=p->k;x->w=p->w;
x->sz=a;
x->l=p->l;
cutdown(p->r,x->r,y,a-SIZE(p->l)-1);
giveback(p);
}else{
y=node::getnew();
y->k=p->k;y->w=p->w;
y->sz=p->sz-a;
y->r=p->r;
cutdown(p->l,x,y->l,a);
giveback(p);
}
}
}
void treeadd(node *&p,node *q){
if (!p){
p=q;
}else{
if (p->w<q->w){
treeadd(p->r,q);
p->sz++;
}else{
q->l=p;q->sz=p->sz+1;
p=q;
}
}
}
void Insert(int i,char a){
node *p=node::getnew();
p->k=a;
node *x,*y;
cutdown(Roots.back(),x,y,i);
x=combine(x,p);x=combine(x,y);
Roots.push_back(x);
curid++;
}
void Delete(int i){
node *x,*y,*z;
cutdown(Roots.back(),x,y,i);
cutdown(y,y,z,1);
giveback(y);
x=combine(x,z);
Roots.push_back(x);
curid++;
}
void Revolve(int a,int b,int c){
node *p,*q,*r,*s;
cutdown(Roots.back(),p,q,a);
cutdown(q,q,r,b-a+1);
cutdown(r,r,s,c-b);
p=combine(p,r);
p=combine(p,q);
p=combine(p,s);
Roots.push_back(p);
curid++;
}
void Print(int a,int x,int y){
node *p=Roots.at(Roots.size()-1-a);
dfs(p,x,y);
puts("");
}
void readstr(vector<char> &a){
char c;
while (c=getchar(),c==10 || c==13 || c==' ');
while (c!=10 && c!=13){
a.push_back(c);
c=getchar();
}
}
int main()
{
scanf("%d",&M);
vector<char> chs;
readstr(chs);
node *r=NULL;
for (int i=0;i<(int)chs.size();i++){
node *p=node::getnew();
p->k=chs[i];
treeadd(r,p);
}
Roots.push_back(r);
curid=0;
char cmd[10];
while (scanf("%s",cmd)!=EOF){
if (cmd[0]=='I'){
int x;
scanf("%d",&x);
scanf("%s",cmd);
Insert(x,cmd[0]);
}else if (cmd[0]=='D'){
int x;
scanf("%d",&x);
Delete(x-1);
}else if (cmd[0]=='P'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Print(x,y-1,z-1);
}else if (cmd[0]=='C'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Revolve(x-1,y-1,z-1);
}
while (!Literbox.empty() && Literbox.front().first<curid-M){
node::getnew(Literbox.front().second);
Literbox.pop();
}
while ((int)Roots.size()>M)Roots.pop_front();
}
return 0;
}
  评论这张
 
阅读(8653)| 评论(20)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017