您的位置:首页 > 其它

POJ 3580 SuperMemo

2011-07-26 11:23 281 查看
  http://poj.org/problem?id=3580

  题目大意说给你一个数列,有区间同加一个数、区间翻转操作、区间滚动操作、删除一个数、插入一个数,查询区间最小值这些操作。

  我是使用Splay乱搞的。其中revolve操作有点头疼,不过仔细观察发现,revolve l r x 其实就是交换(l,r-x)和(r-x+1,r)两个区间。

  代码很长很长很长……而且跟QZ的很像很像很像……

  

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#define INF ~0u>>1
#define NIL SPLAY
#define MN 200005
using namespace std;

int n,m,l,r,x,pos;
char s[10];

struct SPLAYTREE{
struct NODE{
int key,minv,size,add;
bool rev;
NODE *left,*right,*father;
NODE (){}
NODE(int _key):key(_key){minv=_key,size=1,add=0,rev=false;}
}SPLAY[MN],*SP,*root,*head,*tail;

void init(){
SP=NIL;
NIL->key=NIL->minv=INF,NIL->size=0;
NIL->left=NIL->right=NIL->father=NIL;
head=new(++SP)NODE(INF);
head->left=head->right=head->father=NIL;
tail=new(++SP)NODE(INF);
tail->left=tail->right=tail->father=NIL;
head->right=tail,tail->father=head,head->size++;
root=head;
}

void pushdown(NODE *&t){
if(t->rev){
swap(t->left,t->right);
t->left->rev=!t->left->rev;
t->right->rev=!t->right->rev;
t->rev=false;
}
if(t->add){
if(t->left!=NIL){
t->left->key+=t->add;
t->left->minv+=t->add;
t->left->add+=t->add;
}
if(t->right!=NIL){
t->right->key+=t->add;
t->right->minv+=t->add;
t->right->add+=t->add;
}
t->add=0;
}
}

void update(NODE *&t){
t->size=t->left->size+t->right->size+1;
t->minv=min(t->key,min(t->left->minv,t->right->minv));
}

void zig(NODE *&t){
NODE *f=t->father,*r=t->right;
pushdown(f->right);
pushdown(t->left);
pushdown(t->right);
t->father=f->father;
if(f==root) root=t;
else{
if(f->father->left==f) f->father->left=t;
else f->father->right=t;
}
t->right=f,r->father=f,f->father=t,f->left=r;
update(f);update(t);
}

void zag(NODE *&t){
NODE *f=t->father,*l=t->left;
pushdown(f->left);
pushdown(t->left);
pushdown(t->right);
t->father=f->father;
if(f==root) root=t;
else{
if(f->father->left==f) f->father->left=t;
else f->father->right=t;
}
t->left=f,l->father=f,f->father=t,f->right=l;
update(f);update(t);
}

void splay(NODE *&root,NODE *&t){
pushdown(t);
while(root!=t){
if(t->father==root){
if(t->father->left==t) zig(t);
else zag(t);
}
else{
if(t->father->father->left==t->father){
if(t->father->left==t) zig(t->father),zig(t);
else zag(t),zig(t);
}else{
if(t->father->left==t) zig(t),zag(t);
else zag(t->father),zag(t);
}
}
}
}

void insert(int key,int pos){
NODE *t=new(++SP)NODE(key);
t->left=t->right=t->father=NIL;
NODE *r=root,*p;
bool flag=false;
while(pushdown(r),r!=NIL){
p=r,r->size++;
if(r->left->size+1>pos)r=r->left,flag=false;
else pos-=r->left->size+1,r=r->right,flag=true;
}
if(flag) p->right=t;
else p->left=t;
t->father=p;
splay(root,t);
}

void select(NODE *&root,int pos){
NODE *r=root;
while(pushdown(r),r->left->size+1!=pos){
if(r->left->size+1>pos) r=r->left;
else pos-=r->left->size+1,r=r->right;
}
splay(root,r);
}

void remove(int pos){
select(root,pos);
if(root->left==NIL) root=root->right;
else if(root->right==NIL) root=root->left;
else{
select(root->left,root->left->size);
root->left->right=root->right;
root->right->father=root->left;
root=root->left;
}
root->father=NIL;
update(root);
}

void plus(int l,int r,int a){
select(root,l);
select(root->right,r-l);
NODE *t=root->right->left;
t->add+=a,t->key+=a,t->minv+=a;
splay(root,t);
}

void reverse(int l,int r){
select(root,l);
select(root->right,r-l);
NODE *t=root->right->left;
t->rev=!t->rev;
splay(root,t);
}

void revolve(int l,int r,int a){
select(root,l);
select(root->right,r-l);
select(root->right->left,root->right->left->size-a);
select(root->right->left->right,root->right->left->right->size);
NODE *p=root->right->left,*t=root->right->left->right;
p->right=NIL;
p->father->left=t,t->father=p->father;
t->right=p,p->father=t;
update(t);update(p);
splay(root,p);
}

int query(int l,int r){
select(root,l);
select(root->right,r-l);
return root->right->left->minv;
}
}tree;

int main(){
tree.init();
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&x);
tree.insert(x,i);
}

scanf("%d",&m);getchar();
while(m--){
scanf("%s",s);
switch(s[0]){
case 'A':
scanf("%d%d%d",&l,&r,&x);
tree.plus(l,r+2,x);
break;
case 'I':
scanf("%d%d",&pos,&x);
tree.insert(x,pos+1);
break;
case 'D':
scanf("%d",&pos);
tree.remove(pos+1);
break;
case 'M':
scanf("%d%d",&l,&r);
printf("%d\n",tree.query(l,r+2));
break;
case 'R':
if(s[3]=='E'){
scanf("%d%d",&l,&r);
tree.reverse(l,r+2);
}else{
scanf("%d%d%d",&l,&r,&x);
if(x%(r-l+1)) tree.revolve(l,r+2,x%(r-l+1));
}
break;
}
getchar();
}
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: