POJ 3580.SuperMemo
Posted alpha1022
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 3580.SuperMemo相关的知识,希望对你有一定的参考价值。
果断写了个 FHQ Treap……
犯了一些奇怪的错误……
- 一开始更新结点信息写错了。
- 标记下推的时候忘了左右子节点不存在的情况。
代码:
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#define ls(p) tree[p].lson
#define rs(p) tree[p].rson
using namespace std;
const int N = 1e5;
const int M = 1e5;
int n,m;
struct node
{
int val,rnd,min,add,rev,sz;
int lson,rson;
} tree[N + M + 10];
inline int new_node(int v)
{
static int tot = 0;
tree[++tot].val = tree[tot].min = v;
tree[tot].rnd = rand();
tree[tot].sz = 1;
return tot;
}
inline void up(int p)
{
tree[p].sz = tree[ls(p)].sz + 1 + tree[rs(p)].sz;
tree[p].min = min(tree[p].val,min(tree[ls(p)].min,tree[rs(p)].min));
}
inline void down(int p)
{
if(tree[p].add)
{
if(ls(p))
tree[ls(p)].val += tree[p].add,tree[ls(p)].min += tree[p].add,tree[ls(p)].add += tree[p].add;
if(rs(p))
tree[rs(p)].val += tree[p].add,tree[rs(p)].min += tree[p].add,tree[rs(p)].add += tree[p].add;
tree[p].add = 0;
}
if(tree[p].rev)
{
swap(ls(p),rs(p));
if(ls(p))
tree[ls(p)].rev ^= 1;
if(rs(p))
tree[rs(p)].rev ^= 1;
tree[p].rev = 0;
}
}
int merge(int x,int y)
{
if(!x || !y)
return x + y;
down(x),down(y);
if(tree[x].rnd < tree[y].rnd)
{
rs(x) = merge(rs(x),y);
up(x);
return x;
}
else
{
ls(y) = merge(x,ls(y));
up(y);
return y;
}
}
void split(int p,int k,int &x,int &y)
{
if(!p)
{
x = y = 0;
return ;
}
down(p);
if(tree[ls(p)].sz < k)
x = p,split(rs(p),k - tree[ls(p)].sz - 1,rs(p),y);
else
y = p,split(ls(p),k,x,ls(p));
up(p);
}
int p,x,y,z,xx,yy;
int main()
{
tree[0].min = 0x3f3f3f3f;
srand(20070119);
scanf("%d",&n);
int v;
for(register int i = 1;i <= n;++i)
scanf("%d",&v),p = merge(p,new_node(v));
scanf("%d",&m);
char op[10];
int a,b,c;
while(m--)
{
scanf("%s",op);
if(op[0] == 'A')
{
scanf("%d%d%d",&a,&b,&c);
split(p,b,x,z);
split(x,a - 1,x,y);
tree[y].val += c,tree[y].min += c,tree[y].add += c;
p = merge(merge(x,y),z);
}
else if(op[0] == 'R' && op[3] == 'E')
{
scanf("%d%d",&a,&b);
split(p,b,x,z);
split(x,a - 1,x,y);
tree[y].rev ^= 1;
p = merge(merge(x,y),z);
}
else if(op[0] == 'R' && op[3] == 'O')
{
scanf("%d%d%d",&a,&b,&c);
int len = b - a + 1;
c %= len;
split(p,b,x,z);
split(x,a - 1,x,y);
split(y,len - c,xx,yy);
p = merge(merge(x,merge(yy,xx)),z);
}
else if(op[0] == 'I')
{
scanf("%d%d",&a,&b);
split(p,a,x,y);
p = merge(merge(x,new_node(b)),y);
}
else if(op[0] == 'D')
{
scanf("%d",&a);
split(p,a,x,z);
split(x,a - 1,x,y);
p = merge(x,z);
}
else
{
scanf("%d%d",&a,&b);
split(p,b,x,z);
split(x,a - 1,x,y);
printf("%d
",tree[y].min);
p = merge(merge(x,y),z);
}
}
}
以上是关于POJ 3580.SuperMemo的主要内容,如果未能解决你的问题,请参考以下文章
POJ 3580 - SuperMemo - [伸展树splay]