首页 > 代码库 > POJ 3580 SuperMemo Splay
POJ 3580 SuperMemo Splay
题目大意:维护一个序列,提供一些操作:
1.将一个区间加上一个值
2.翻转一个区间
3.将一个区间内的数字旋转T次(每次旋转区间内每个元素向右移一位,最右一个移动到最左面去)
4.在一个元素后面插入一个数
5.删除某个元素
6.查询区间最小值
写过BZOJ那几道Splay之后这题就变得非常水了。。。只是有几个要点需要注意:
1.操作3的T可能大于区间长度 还可能是负的 所以一定要取模
2.操作3非常容易弄反 是把后T个数字移动到前面来 不是把前T个数字移动到后面去
4.空节点null的初值要设为极大值 0x3f不够大 直接设成2147483647比较好
5.下传标记的时候一定要特判节点是不是null 不然null会被加爆 切记!
6.看题解要认真仔细 比如说我的要点没有第三条 你看到了么
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define INF 0x7fffffff using namespace std; struct abcd{ abcd *fa,*ls,*rs; int siz,num,minnum; int add_mark,rev_mark; abcd(int x); void Push_Up(); void Push_Down(); }*null=new abcd(INF),*root=null; abcd :: abcd(int x) { fa=ls=rs=null; siz=1; if(x==INF) siz=0; num=minnum=x; add_mark=rev_mark=0; } void abcd :: Push_Up() { siz=ls->siz+rs->siz+1; minnum=min(ls->minnum,rs->minnum); minnum=min(minnum,num); } void abcd :: Push_Down() { if(add_mark) { if(ls!=null) { ls->add_mark+=add_mark; ls->num+=add_mark; ls->minnum+=add_mark; } if(rs!=null) { rs->add_mark+=add_mark; rs->num+=add_mark; rs->minnum+=add_mark; } add_mark=0; } if(rev_mark) { ls->rev_mark^=1; rs->rev_mark^=1; swap(ls->ls,ls->rs); swap(rs->ls,rs->rs); rev_mark=0; } } void Zig(abcd *x) { abcd *y=x->fa; y->Push_Down(); x->Push_Down(); y->ls=x->rs; x->rs->fa=y; x->rs=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); if(y==root) root=x; } void Zag(abcd *x) { abcd *y=x->fa; y->Push_Down(); x->Push_Down(); y->rs=x->ls; x->ls->fa=y; x->ls=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); if(y==root) root=x; } void Splay(abcd *x,abcd *Tar) { while(1) { abcd *y=x->fa,*z=y->fa; if(y==Tar) break; if(z==Tar) { if(x==y->ls)Zig(x); else Zag(x); break; } if(x==y->ls) { if(y==z->ls) Zig(y); Zig(x); } else { if(y==z->rs) Zag(y); Zag(x); } } x->Push_Up(); } void Find(abcd *x,int y,abcd *z) { while(1) { x->Push_Down(); if(y<=x->ls->siz) x=x->ls; else { y-=x->ls->siz; if(y==1) break; y--; x=x->rs; } } Splay(x,z); } void Insert(abcd *&x,int y,abcd *z) { if(x==null) { x=new abcd(y); x->fa=z; Splay(x,null); return ; } x->Push_Down(); Insert(x->rs,y,x); } int n,m; int main() { int i,x,y,z; char p[10]; cin>>n; Insert(root,19980402,null); for(i=1;i<=n;i++) scanf("%d",&x),Insert(root,x,null); Insert(root,19980402,null); cin>>m; for(i=1;i<=m;i++) { scanf("%s",p); if(p[0]=='A') { scanf("%d%d%d",&x,&y,&z); Find(root,x,null); Find(root,y+2,root); abcd *temp=root->rs->ls; temp->add_mark+=z; temp->num+=z; temp->minnum+=z; } else if(p[0]=='R'&&p[3]=='E') { scanf("%d%d",&x,&y); Find(root,x,null); Find(root,y+2,root); abcd *temp=root->rs->ls; temp->rev_mark^=1; swap(temp->ls,temp->rs); } else if(p[0]=='R'&&p[3]=='O') { scanf("%d%d%d",&x,&y,&z); z%=y-x+1; z+=y-x+1; z%=y-x+1; if(!z) continue; Find(root,y-z+1,null); Find(root,y+2,root); abcd *temp=root->rs->ls; root->rs->ls=null; root->rs->Push_Up(); root->Push_Up(); Find(root,x,null); Find(root,x+1,root); root->rs->ls=temp; temp->fa=root->rs; root->rs->Push_Up(); root->Push_Up(); } else if(p[0]=='I') { scanf("%d%d",&x,&y); Find(root,x+1,null); Find(root,x+2,root); Insert(root->rs->ls,y,root->rs); } else if(p[0]=='D') { scanf("%d",&x); Find(root,x,null); Find(root,x+2,root); root->rs->ls=null; root->rs->Push_Up(); root->Push_Up(); } else { scanf("%d%d",&x,&y); Find(root,x,null); Find(root,y+2,root); printf("%d\n",root->rs->ls->minnum); } } }
POJ 3580 SuperMemo Splay
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。