您的位置:首页 > 其它

可持久化Treap——SPOJ ADALIST

2017-04-12 22:54 197 查看
题目链接:http://www.spoj.com/problems/ADALIST/

题意:有3种操作,要求能够在第K个位置加入元素,删除第K个位置的元素,输出第K个位置的元素

分析:这道题可以使用vector或者dequeue暴力跑过,还可以用更省时的Treap来做。复习一下可持久化Treap:

插入:在第K位置split,合并三棵Treap

删除:在第K位置split,再split包含第K个元素的Treap,一边一个(即第K个),另一边是剩下的元素,再合并除了第K个元素的Treap外的两个Treap

查询:二叉搜索树直接查询就可以

AC代码:

/*************************************************************************
> File Name: test.cpp
> Author: Akira
> Mail: qaq.febr2.qaq@gmail.com
************************************************************************/

#include<bits/stdc++.h>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
#define MST(a,b) memset(a,b,sizeof(a))
#define CLR(a) MST(a,0)
#define Sqr(a) ((a)*(a))
using namespace std;

#define MaxN 100001
#define MaxM MaxN*10
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
const int mod = 1E9+7;
const double eps = 1e-6;
#define bug cout<<88888888<<endl;
#define debug(x) cout << #x" = " << x << endl;

struct Node
{
Node *left, *right;
int val, prio, size;
Node():left(0),right(0){}
}*root,pool[6*MaxN];
inline int size(Node *n){ return n?n->size:0;}
inline void update_size(Node *n){if (n) n->size=1+size(n->left)+size(n->right);}
void merge(Node *&n, Node *a, Node *b)
{
if(!a||!b) n=a?a:b;
else if( a->prio < b->prio)
merge(a->right, a->right, b), n=a;
else
merge(b->left, a, b->left), n=b;
update_size(n);
}

void split(Node *n, Node *&a, Node *&b, int key, int add=0)
{
if(!n) return void(a=b=0);
int cnt = add+ size(n->left) +1;
if(cnt < key)
split(n->right, n->right, b, key, cnt), a=n;
else
split(n->left, a, n->left, key, add), b=n;
update_size(n);
}

void insert(int key, int val)
{
static int ptr = 0;
Node*x =  &pool[ptr++];
x->val = val;
x->prio = rand();

Node *a, *b;
split(root, a, b, key);
merge(a,a,x);
merge(root,a,b);
}

void remove(int key)
{
Node *a,*b,*t;
split(root,a,b,key);
split(b,t,b,2);
merge(root,a,b);
}

int find(int key, Node *n=root, int add=0)
{
if(!n) return -1;
int cnt = add + size(n->left) + 1;
if(cnt==key)
return n->val;
else if( cnt < key)
return find(key, n->right, cnt);
else
return find(key, n->left, add);
}

int main()
{
//std::ios::sync_with_stdio(false);
int n,q,a,b,c;
scanf("%d%d", &n, &q);
for(int i=1;i<=n;i++)
{
scanf("%d", &a);
insert(i, a);
}
while(q--)
{
scanf("%d%d", &a, &b);
if(a==1)
{
scanf("%d", &c);
insert(b,c);
}
else if(a==2) remove(b);
else printf("%d\n", find(b));
}
//system("pause");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Treap