1. 程式人生 > >P3391 【模板】文藝平衡樹(Splay)

P3391 【模板】文藝平衡樹(Splay)

spa 標題 -s gets 需要 () 序列 代碼 輸入

題目背景

這是一道經典的Splay模板題——文藝平衡樹。

題目描述

您需要寫一種數據結構(可參考題目標題),來維護一個有序數列,其中需要提供以下操作:翻轉一個區間,例如原有序序列是5 4 3 2 1,翻轉區間是[2,4]的話,結果是5 2 3 4 1

輸入輸出格式

輸入格式:

第一行為n,m n表示初始序列有n個數,這個序列依次是(1,2, \cdots n-1,n)(1,2,?n?1,n) m表示翻轉操作次數

接下來m行每行兩個數 [l,r][l,r] 數據保證 1 \leq l \leq r \leq n1lrn

輸出格式:

輸出一行n個數字,表示原始序列經過m次變換後的結果

輸入輸出樣例

輸入樣例#1:
5 3
1 3
1 3
1 4
輸出樣例#1:
4 3 2 1 5

說明

n, m \leq 100000n,m100000

代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100010
using namespace std;
int n,m,tot;
int root,siz[MAXN],fa[MAXN],flag[MAXN],key[MAXN],ch[MAXN][2],cnt[MAXN],ans[MAXN];
void updeat(int rt){ int l=ch[rt][0],r=ch[rt][1]; siz[rt]=siz[l]+siz[r]+1; } void pushdown(int now){ if(flag[now]){ flag[ch[now][0]]^=1; flag[ch[now][1]]^=1; swap(ch[now][0],ch[now][1]); flag[now]=0; } } int getson(int x){ return ch[fa[x]][1]==x; } void
rotate(int x){ int y=fa[x],z=fa[y],b=getson(x),c=getson(y),a=ch[x][!b]; if(z) ch[z][c]=x; else root=x; fa[x]=z; if(a) fa[a]=y; ch[y][b]=a; ch[x][!b]=y;fa[y]=x; updeat(y);updeat(x); } void splay(int x,int i){ while(fa[x]!=i){ int y=fa[x],z=fa[y]; if(z==i){ rotate(x); }else{ if(getson(x)==getson(y)){ rotate(y); rotate(x); }else{ rotate(x); rotate(x); } } } } int findx(int x){ int now=root; while(1){ pushdown(now); if(ch[now][0]&&x<=siz[ch[now][0]]) now=ch[now][0]; else{ int tmp=(ch[now][0]?siz[ch[now][0]]:0)+1; if(x<=tmp) return now; x-=tmp; now=ch[now][1]; } } } int build(int l,int r,int f){ int now=(l+r)/2; fa[now]=f; key[now]=ans[now]; if(l<now) ch[now][0]=build(l,now-1,now); if(r>now) ch[now][1]=build(now+1,r,now); updeat(now); return now; } void print(int now){ pushdown(now); if(ch[now][0]) print(ch[now][0]); ans[++tot]=key[now]; if(ch[now][1]) print(ch[now][1]); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n+2;i++) ans[i]=i-1; root=build(1,n+2,0); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); y=y+2; int xx=findx(x),yy=findx(y); splay(xx,0);splay(yy,xx); flag[ch[ch[root][1]][0]]^=1; } print(root); for(int i=1;i<=n;i++) printf("%d ",ans[i+1]); }

P3391 【模板】文藝平衡樹(Splay)