您的位置:首页 > 其它

UVA 11922(用splay实现可分裂和合并的序列)

2015-09-30 20:28 375 查看
介绍一下,splay保存的序列,序列不再是有序的,只是维持相对位置,splay主要实现对第k个位置的元素旋转到根,然后实现分裂与合并,要实现找到第k个元素,就必须维护一个s(以该节点为根的子树有多少节点)。

对于本题目而言,要实现翻转,可以类比线段树来加惰性标志,实现翻转。

#include <cstdlib>
#include <algorithm>
#include <iostream>
#define rep1(i,x,y) for(int i=x;i<=y;i++)
typedef struct node* pointer;
struct node{
pointer ch[2];
int v,s,flip;
node(int v=0):v(v){ch[0]=ch[1]=NULL; s=1; flip = 0; }
int cmp(int x){
int pre = (ch[0]==NULL ? 0 : ch[0]->s);
if(pre + 1 == x) return -1;
return pre>= x ? 0 : 1;
}
void maintain(){
s = 1;
if(ch[0]!=NULL) s+=ch[0]->s;
if(ch[1]!=NULL) s+=ch[1]->s;
}
void pushdown(){
if(flip){
flip=0;
std::swap(ch[0],ch[1]);
if(ch[0] != NULL) ch[0]->flip ^= 1;
if(ch[1] != NULL) ch[1]->flip ^= 1;
}
}
};
pointer root;
void init(int n){
root = new node(1);
pointer u = root; u->s = n;
rep1(i,2,n){
u->ch[1] = new node(i);
u->ch[1]->s = n-i+1;
u = u->ch[1];
}
}
void rotate(pointer& o,int d){
pointer te = o->ch[d^1];
o->ch[d^1] = te->ch[d];
te->ch[d] = o;
o->maintain(); te->maintain();
o = te;
}
void splay(pointer& o ,int k){
o->pushdown();
int d = o->cmp(k);
if(d != -1){
if(d==1) k -= (o->ch[0]==NULL ? 0 : o->ch[0]->s) + 1;
o->ch[d]->pushdown();
pointer te = o->ch[d];
int d2 = te->cmp(k);
if(d2!=-1){
int k2 = (d2 == 0 ? k : k-(te->ch[0]==NULL ? 0 : te->ch[0]->s)-1);
splay(te->ch[d2],k2);
if(d2 == d) rotate(o,d^1);
else rotate(o->ch[d],d);
}
rotate(o,d^1);
}
}
pointer merge_(pointer le, pointer ri){
splay(le,le->s);
le->ch[1] = ri;
le->maintain();
return le;
}
void split(pointer o,int k,pointer &le , pointer &ri){
splay(o,k);
le = o;
ri = o->ch[1];
le->ch[1] = NULL;
le->maintain();
}
#include <cstdio>
#include <algorithm>
#include <cstring>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define out(str) std::cout<<str<<std::endl;
typedef long long ll;
const int N = 2e4 + 100;
const int M = 6e4 + 100;

int n,m;
void dfs(pointer u){
u->pushdown();
if(u->ch[0] != NULL) dfs(u->ch[0]);
if(u->v > 1)printf("%d\n",u->v-1);
if(u->ch[1] != NULL) dfs(u->ch[1]);
}
int main()
{
scanf("%d %d",&n,&m);
init(n+1);
int a, b;
while(m--){
scanf("%d %d",&a,&b);
pointer le , mid , ri , o;
split(root , a , le , o);
split(o , b-a+1, mid , ri);
mid->flip ^= 1;
root = merge_(merge_(le,ri), mid);
}
dfs(root);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: