BZOJ1500 维护数列 treap实现
2013-04-14 21:59
399 查看
很早以前听叉姐说treap可以写这个题,然后围观了一下神代码,然后~发现这个比用splay写起来简单很多。
这里首先要改变一下treap的写法。正常的treap是每个节点维护一个权值,然后根据权值去旋转,这样我们可以把一棵treap分成两棵,方法是造一个没用的节点然后给这个结点一个极大权值,这样这个节点就是根结点,它的左右两棵子村就是把原来的树分成了两棵,这样我们就能很轻松的提取出一个区间并像splay一样维护。
然后~其实吧~我用的不是旋转的方法提取区间,而是用split和merge把一棵树拆成两棵和把两棵合并成一棵。具体的实现可以看我下面的代码。
一开始这个题老是TLE,后来发现竟然是因为我用了系统的rand函数导致的,然后~自己写了一个随机数生成器~然后过掉~但是还是比splay慢【囧
SPOJ1470我还没去尝试~不过我觉得目测应该会TLE掉~毕竟SPOJ连优化不好的splay都会TLE掉。唉
这里首先要改变一下treap的写法。正常的treap是每个节点维护一个权值,然后根据权值去旋转,这样我们可以把一棵treap分成两棵,方法是造一个没用的节点然后给这个结点一个极大权值,这样这个节点就是根结点,它的左右两棵子村就是把原来的树分成了两棵,这样我们就能很轻松的提取出一个区间并像splay一样维护。
然后~其实吧~我用的不是旋转的方法提取区间,而是用split和merge把一棵树拆成两棵和把两棵合并成一棵。具体的实现可以看我下面的代码。
一开始这个题老是TLE,后来发现竟然是因为我用了系统的rand函数导致的,然后~自己写了一个随机数生成器~然后过掉~但是还是比splay慢【囧
SPOJ1470我还没去尝试~不过我觉得目测应该会TLE掉~毕竟SPOJ连优化不好的splay都会TLE掉。唉
#define INF 2000000000 #define N 500010 struct Node; Node *null,*root; struct Node { int w,sz,val,sum,ls,rs,ss,lzy1,lzy2; Node *lft,*rht; void split(int,Node*&,Node*&); void same(int v) { if(this==null) return; lzy2=val=v; sum=v*sz; ls=rs=ss=max(sum,v); } void rev() { if(this==null) return; lzy1^=1; swap(lft,rht); swap(ls,rs); } Node *pushup() { sz=lft->sz+1+rht->sz; sum=lft->sum+val+rht->sum; ls=max(lft->ls,lft->sum+val+max(0,rht->ls)); rs=max(rht->rs,rht->sum+val+max(0,lft->rs)); ss=max(0,lft->rs)+val+max(0,rht->ls); ss=max(ss,max(lft->ss,rht->ss)); return this; } Node *pushdown() { if(lzy1) { lft->rev(); rht->rev(); lzy1=0; } if(lzy2!=-INF) { lft->same(lzy2); rht->same(lzy2); lzy2=-INF; } return this; } }; Node *merge(Node *p,Node *q) { if(p==null) return q; if(q==null) return p; if(p->w<q->w) { p->pushdown(); p->rht=merge(p->rht,q); return p->pushup(); } q->pushdown(); q->lft=merge(p,q->lft); return q->pushup(); } void Node::split(int need,Node *&p,Node *&q) { if(this==null) { p=q=null; return; } pushdown(); if(lft->sz>=need) { lft->split(need,p,q); lft=null; pushup(); q=merge(q,this); return; } rht->split(need-(lft->sz+1),p,q); rht=null; pushup(); p=merge(this,p); return; } Node data ,*pool ; int top,cnt; Node* newnode(int c) { Node *x; if(top) x=pool[top--]; else x=&data[cnt++]; x->lft=x->rht=null; x->sz=1; x->lzy1=0; x->lzy2=-INF; x->val=x->sum=x->ls=x->rs=x->ss=c; x->w=rands(); return x; } void init() { cnt=1; top=0; null=&data[0]; null->sz=null->sum=0; null->val=null->ls=null->rs=null->ss=-INF; null->lzy1=0; null->lzy2=-INF; null->lft=null->rht=null; } //--------------------------------------------------------- void erase(Node *rt) { if(rt==null) return; erase(rt->lft); erase(rt->rht); pool[++top]=rt; } int n,m; char ord[20]; int a,b,c; int main () { init(); root=null; n=fastget(); m=fastget(); for(int i=0;i<n;i++) { a=fastget(); root=merge(root,newnode(a)); } while (m--) { scanf("%s",ord); Node *p,*q,*r,*s; if(ord[0]=='I') { a=fastget(); n=fastget(); root->split(a,p,q); for(int i=0;i<n;i++) { b=fastget(); p=merge(p,newnode(b)); } root=merge(p,q); }else if(ord[0]=='D') { a=fastget(); b=fastget(); b=a+b-1; root->split(a-1,p,q); q->split(b-a+1,r,s); erase(r); root=merge(p,s); }else if(ord[0]=='M' && ord[2]=='K') { a=fastget(); b=fastget(); c=fastget(); b=b+a-1; root->split(a-1,p,q); q->split(b-a+1,r,s); r->same(c); root=merge(p,merge(r,s)); }else if(ord[0]=='R') { a=fastget(); b=fastget(); b=b+a-1; root->split(a-1,p,q); q->split(b-a+1,r,s); r->rev(); root=merge(p,merge(r,s)); }else if(ord[0]=='G') { a=fastget(); b=fastget(); b=a+b-1; root->split(a-1,p,q); q->split(b-a+1,r,s); fastput(r->sum); root=merge(p,merge(r,s)); } else if(ord[0]=='M') fastput(root->ss); } return 0; }
相关文章推荐
- [BZOJ1500][NOI2005]维护数列(无旋Treap)
- 【bzoj1500】 noi2005—维护数列
- bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)
- splay BZOJ1500 NOI2005 维护数列
- BZOJ 1500 维护(维修?)数列
- 【NOI2005】【JZOJ 2413】【BZOJ 1500】维护数列
- 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
- [您有新的未分配科技点] 无旋treap:从单点到区间(例题 BZOJ1500&NOI2005 维护数列 )
- NOI 2005 BZOJ 1500 维护数列
- [bzoj1500][luogu2042][cogs339][codevs1758]维修数列(维护数列)
- 维护数列 洛谷2042 bzoj1500 NOI2005
- BZOJ 1500([NOI2005]维修数列-Splay的数列维护)
- 【平衡树维护序列】BZOJ1500(NOI2005)[维修数列]题解
- Bzoj 1500 维护数列
- [bzoj1500][NOI2005]维修数列_非旋转Treap
- BZOJ1500: [NOI2005]维修数列 Splay维护序列
- BZOJ1056 [HAOI2008]排名系统 treap实现map
- BZOJ 1500: [NOI2005]维修数列 (splay tree)
- BZOJ 1500 [NOI2005]维修数列
- [BZOJ1500]NOI2005 维修数列|splay