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

洛谷P3391 【模板】文藝平衡樹(Splay)(FHQ Treap)

and fine 背景 clas bad 例如 spa 個數 static

題目背景

這是一道經典的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,?n1,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

FHQ無敵,

解決區間問題的時候按照$r$分成兩個

再按照$l$分成兩個

那麽我們就得到了需要翻轉的區間

然後愉快的打標記就好啦

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4
#include<ctime> 5 #include<cstdlib> 6 using namespace std; 7 #define ls T[now].ch[0] 8 #define rs T[now].ch[1] 9 const int MAXN=1e6+10; 10 inline char nc() 11 { 12 static char buf[MAXN],*p1=buf,*p2=buf; 13 return p1==p2&&(p2=(p1=buf)+fread(buf,1,MAXN,stdin),p1==p2)?EOF:*p1++;
14 } 15 inline int read() 16 { 17 char c=nc();int x=0,f=1; 18 while(c<0||c>9){if(c==-)f=-1;c=nc();} 19 while(c>=0&&c<=9){x=x*10+c-0,c=nc();} 20 return x*f; 21 } 22 struct node 23 { 24 int ch[2],val,siz,pri,mark; 25 }T[MAXN]; 26 int tot=0; 27 int x,y,z,root=0,n,m; 28 int newnode(int v) 29 { 30 T[++tot].siz=1; 31 T[tot].val=v; 32 T[tot].pri=rand(); 33 return tot; 34 } 35 void update(int now) 36 { 37 T[now].siz=T[ls].siz+T[rs].siz+1; 38 } 39 int Build(int l,int r) 40 { 41 if(l>r) return 0; 42 int mid=(l+r)>>1; 43 int now=newnode(mid-1); 44 ls=Build(l,mid-1); 45 rs=Build(mid+1,r); 46 update(now); 47 return now; 48 } 49 void pushdown(int now) 50 { 51 if(T[now].mark&&now) 52 { 53 swap(ls,rs); 54 if(ls) T[ls].mark^=1; 55 if(rs) T[rs].mark^=1; 56 T[now].mark=0; 57 } 58 } 59 void split(int now,int k,int &x,int &y) 60 { 61 if(!now) {x=y=0;return ;} 62 pushdown(now); 63 if(T[ls].siz<k) 64 x=now,split(rs,k-T[ls].siz-1,rs,y); 65 else 66 y=now,split(ls,k,x,ls); 67 update(now); 68 } 69 int merge(int x,int y) 70 { 71 if(!x||!y) return x+y; 72 pushdown(x);pushdown(y); 73 if(T[x].pri<T[y].pri) 74 { 75 T[x].ch[1]=merge(T[x].ch[1],y); 76 update(x); 77 return x; 78 } 79 else 80 { 81 T[y].ch[0]=merge(x,T[y].ch[0]); 82 update(y); 83 return y; 84 } 85 } 86 void dfs(int now) 87 { 88 pushdown(now); 89 if(T[now].ch[0]) dfs(T[now].ch[0]); 90 if(T[now].val>=1&&T[now].val<=n) printf("%d ",T[now].val); 91 if(T[now].ch[1]) dfs(T[now].ch[1]); 92 } 93 int main() 94 { 95 #ifdef WIN32 96 freopen("a.in","r",stdin); 97 #else 98 #endif 99 //srand((unsigned)time(NULL)); 100 n=read(),m=read(); 101 root=Build(1,n+2); 102 while(m--) 103 { 104 int l=read(),r=read(); 105 int a,b,c,d; 106 split(root,r+1,a,b); 107 split(a,l,c,d); 108 T[d].mark^=1; 109 root=merge( merge(c,d) ,b ); 110 } 111 dfs(root); 112 return 0; 113 }

洛谷P3391 【模板】文藝平衡樹(Splay)(FHQ Treap)