網上有許多題,就是給定一個序列,要你支持幾種操做:A、B、C、D。一看另外一道題,又是一個序列要支持幾種操做:D、C、B、A。尤爲是咱們這裏的某人,出模擬試題,竟然還出了一道這樣的,真是沒技術含量……這樣 我也出一道題,我出這一道的目的是爲了讓你們之後作這種題目有一個「庫」能夠依靠,沒有什麼其餘的意思。這道題目 就叫序列終結者吧。【問題描述】 給定一個長度爲N的序列,每一個序列的元素是一個整數(廢話)。要支持如下三種操做: 1. 將 [L, R] 這個區間內的全部數加上 V。 2. 將 [L,R] 這個區間翻轉,好比 1 2 3 4 變成 4 3 2 1。3. 求 [L,R] 這個區間中的最大值。最開始全部元素都是 0。php
第一行兩個整數 N,M。M 爲操做個數。如下 M 行,每行最多四個整數,依次爲 K, L, R, V。K 表示是第幾種操做,若是不是第 1 種操做則 K 後面只有兩個數。對於每一個第3種操做,給出正確的回答。ios
【數據範圍】N<=50000,M<=100000。ide
這題還真不能用 線段樹 作,Splay 是一個不錯的選擇ui
對於操做 1 將全部 [L, R] 中的數加上一個常量,能夠對 Splay 樹中的節點增長一個 add 域,表示以該節點爲根中序遍歷所得的數列中每一個數要增長 add,每次執行的時候,先將 L-1 旋轉到根,再把 R+1 旋轉成根的兒子節點,那麼,[L, R] 區間的數列就在 R+1 的左子樹中了,對 R+1 的左兒子執行更新操做便可,相似於線段樹的懶操做spa
對於操做 2 將全部 [L, R] 中的數翻轉,能夠對 Splay 樹中的節點增長一個 rev 域,表示以該節點爲根中序遍歷所得的數列是否須要翻轉,更新的時候仍是和操做 1 同樣,將 L-1 旋轉到根,R+1 旋轉成爲 L-1 的孩子,直接對 R+1 的左兒子更新code
對於操做 3,增長一個 Max 域,表示以該節點爲根中序遍歷獲得的數列中最大值是多少,詢問時,將 L-1 旋轉到根,R+1 旋轉成 L-1 的孩子,詢問 R-1 的左兒子的 Max 便可blog
這裏說一點細節:因爲是維護數列,且涉及到區間翻轉操做,因此還要增長一個 Size 域,表示以它爲根的中序遍歷獲得的數列的個數是多少,用它來實現數列中的定位get
因爲涉及到翻轉和統一加權操做,pushDown 和 pushUp 操做必定要想好在哪些地方須要執行string
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=100005, INF=0x7fffffff; 8 9 struct Splay_Tree { 10 struct Node { 11 int val, Max, add, Size, son[2]; 12 bool rev; 13 void init(int _val) { 14 val=Max=_val, Size=1; 15 add=rev=son[0]=son[1]=0; 16 } 17 } T[N]; 18 int fa[N], root; 19 20 void pushUp(int x) { 21 T[x].Max=T[x].val, T[x].Size=1; 22 if(T[x].son[0]) { 23 T[x].Max=max(T[x].Max, T[T[x].son[0]].Max); 24 T[x].Size+=T[T[x].son[0]].Size; 25 } 26 if(T[x].son[1]) { 27 T[x].Max=max(T[x].Max, T[T[x].son[1]].Max); 28 T[x].Size+=T[T[x].son[1]].Size; 29 } 30 } 31 32 void pushDown(int x) { 33 if(x==0) return; 34 if(T[x].add) { 35 if(T[x].son[0]) { 36 T[T[x].son[0]].val+=T[x].add; 37 T[T[x].son[0]].Max+=T[x].add; 38 T[T[x].son[0]].add+=T[x].add; 39 } 40 if(T[x].son[1]) { 41 T[T[x].son[1]].val+=T[x].add; 42 T[T[x].son[1]].Max+=T[x].add; 43 T[T[x].son[1]].add+=T[x].add; 44 } 45 T[x].add=0; 46 } 47 if(T[x].rev) { 48 if(T[x].son[0]) T[T[x].son[0]].rev^=1; 49 if(T[x].son[1]) T[T[x].son[1]].rev^=1; 50 swap(T[x].son[0], T[x].son[1]); 51 T[x].rev=0; 52 } 53 } 54 55 void Rotate(int x, int kind) { 56 int y=fa[x], z=fa[y]; 57 T[y].son[!kind]=T[x].son[kind], fa[T[x].son[kind]]=y; 58 T[x].son[kind]=y, fa[y]=x; 59 T[z].son[T[z].son[1]==y]=x, fa[x]=z; 60 pushUp(y); 61 } 62 63 void Splay(int x, int goal) { 64 if(x==goal) return; 65 while(fa[x]!=goal) { 66 int y=fa[x], z=fa[y]; 67 pushDown(z), pushDown(y), pushDown(x); 68 int rx=T[y].son[0]==x, ry=T[z].son[0]==y; 69 if(z==goal) Rotate(x, rx); 70 else { 71 if(rx==ry) Rotate(y, ry); 72 else Rotate(x, rx); 73 Rotate(x, ry); 74 } 75 } 76 pushUp(x); 77 if(goal==0) root=x; 78 } 79 80 int Select(int pos) { 81 int u=root; 82 pushDown(u); 83 while(T[T[u].son[0]].Size!=pos) { 84 if(pos<T[T[u].son[0]].Size) u=T[u].son[0]; 85 else { 86 pos-=T[T[u].son[0]].Size+1; 87 u=T[u].son[1]; 88 } 89 pushDown(u); 90 } 91 return u; 92 } 93 94 void update(int L, int R, int val) { 95 int u=Select(L-1), v=Select(R+1); 96 Splay(u, 0); 97 Splay(v, u); 98 T[T[v].son[0]].Max+=val; 99 T[T[v].son[0]].val+=val; 100 T[T[v].son[0]].add+=val; 101 } 102 103 void Reverse(int L, int R) { 104 int u=Select(L-1), v=Select(R+1); 105 Splay(u, 0); 106 Splay(v, u); 107 T[T[v].son[0]].rev^=1; 108 } 109 110 int query(int L, int R) { 111 int u=Select(L-1), v=Select(R+1); 112 Splay(u, 0); 113 Splay(v, u); 114 return T[T[v].son[0]].Max; 115 } 116 117 int build(int L, int R) { 118 if(L>R) return 0; 119 if(L==R) return L; 120 int mid=(L+R)>>1, sL, sR; 121 T[mid].son[0]=sL=build(L, mid-1); 122 T[mid].son[1]=sR=build(mid+1, R); 123 fa[sL]=fa[sR]=mid; 124 pushUp(mid); 125 return mid; 126 } 127 128 void init(int n) { 129 T[0].init(-INF), T[1].init(-INF), T[n+2].init(-INF); 130 for(int i=2; i<=n+1; i++) T[i].init(0); 131 root=build(1, n+2), fa[root]=0; 132 fa[0]=0, T[0].son[1]=root, T[0].Size=0; 133 } 134 }; 135 136 Splay_Tree hehe; 137 138 int main() { 139 int n, m; 140 scanf("%d%d", &n, &m); 141 hehe.init(n); 142 for(int i=0, a, b, c, d; i<m; i++) { 143 scanf("%d", &a); 144 if(a==1) { 145 scanf("%d%d%d", &b, &c, &d); 146 hehe.update(b, c, d); 147 } 148 else if(a==2) { 149 scanf("%d%d", &b, &c); 150 hehe.Reverse(b, c); 151 } 152 else { 153 scanf("%d%d", &b, &c); 154 printf("%d\n", hehe.query(b, c)); 155 } 156 } 157 return 0; 158 }