1. 程式人生 > >洛谷P3721 單旋

洛谷P3721 單旋

emp const ons 分類討論 找規律 isp printf 操作 chang

什麽毒瘤......

題意:模擬一棵單旋splay,求每次插入,splay最值,刪除最值的操作次數。

解:乍一看感覺很神,又因為是LCT題單上的,然後就折磨了我好久,最後跑去看題解...

居然是手玩找規律題!我瘋了。

是這樣的,因為它只會單旋,而且只會splay最值,手玩一下就發現整個樹的形態不變......就是把一個節點拿上去當根了,然後它的子節點代替它的位置。

插入,根據普通splay插入可知它一定接在前驅/後繼的下面。找到深度大的那個就行了。

具體來說,用一棵值域線段樹維護每個權值的深度。同時還要記錄根,fa,son,樹中節點數...

線段樹要支持區間加,單點修改,查詢第k大,區間求和,單點查詢等功能。

大力分類討論,註意一波細節,然後就A了...

技術分享圖片
  1 #include <cstdio>
  2 #include <algorithm>
  3 
  4 const int N = 100010;
  5 
  6 struct Node {
  7     int f, x;
  8 }node[N];
  9 
 10 int tag[N * 4], sum[N * 4], fa[N], s[N][2], X[N], temp;
 11 
 12 inline void pushdown(int o) {
 13     if(tag[o]) {
 14         tag[o << 1
] += tag[o]; 15 tag[o << 1 | 1] += tag[o]; 16 tag[o] = 0; 17 } 18 return; 19 } 20 21 int ask(int p, int l, int r, int o) { 22 if(l == r) { 23 if(!sum[o]) { 24 tag[o] = 0; 25 } 26 return tag[o]; 27 } 28 pushdown(o);
29 int mid = (l + r) >> 1; 30 if(p <= mid) { 31 return ask(p, l, mid, o << 1); 32 } 33 else { 34 return ask(p, mid + 1, r, o << 1 | 1); 35 } 36 } 37 38 void change(int p, int v, int l, int r, int o) { 39 if(l == r) { 40 if(v == -1) { 41 sum[o] = tag[o] = 0; 42 } 43 else { 44 sum[o] = 1; 45 tag[o] = v; 46 } 47 return; 48 } 49 pushdown(o); 50 int mid = (l + r) >> 1; 51 if(p <= mid) { 52 change(p, v, l, mid, o << 1); 53 } 54 else { 55 change(p, v, mid + 1, r, o << 1 | 1); 56 } 57 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 58 return; 59 } 60 61 int getK(int k, int l, int r, int o) { 62 if(l == r) { 63 return r; 64 } 65 int mid = (l + r) >> 1; 66 if(k <= sum[o << 1]) { 67 return getK(k, l, mid, o << 1); 68 } 69 else { 70 return getK(k - sum[o << 1], mid + 1, r, o << 1 | 1); 71 } 72 } 73 74 int getSum(int L, int R, int l, int r, int o) { 75 if(L <= l && r <= R) { 76 return sum[o]; 77 } 78 int mid = (l + r) >> 1, ans = 0; 79 if(L <= mid) { 80 ans += getSum(L, R, l, mid, o << 1); 81 } 82 if(mid < R) { 83 ans += getSum(L, R, mid + 1, r, o << 1 | 1); 84 } 85 return ans; 86 } 87 88 void add(int L, int R, int v, int l, int r, int o) { 89 if(L <= l && r <= R) { 90 tag[o] += v; 91 return; 92 } 93 pushdown(o); 94 int mid = (l + r) >> 1; 95 if(L <= mid) { 96 add(L, R, v, l, mid, o << 1); 97 } 98 if(mid < R) { 99 add(L, R, v, mid + 1, r, o << 1 | 1); 100 } 101 return; 102 } 103 104 int main() { 105 int q, f, x, siz = 0, rt; 106 scanf("%d", &q); 107 for(int i = 1; i <= q; i++) { 108 scanf("%d", &node[i].f); 109 if(node[i].f == 1) { 110 scanf("%d", &node[i].x); 111 X[++temp] = node[i].x; 112 } 113 } 114 std::sort(X + 1, X + temp + 1); 115 temp = std::unique(X + 1, X + temp + 1) - X - 1; 116 for(int i = 1; i <= q; i++) { 117 f = node[i].f; 118 if(f == 1) { 119 x = std::lower_bound(X + 1, X + temp + 1, node[i].x) - X; 120 int k = getSum(1, x, 1, temp, 1), d; 121 if(!siz) { 122 d = 1; 123 rt = x; 124 } 125 else if(!k) { 126 int r = getK(1, 1, temp, 1); 127 d = ask(r, 1, temp, 1) + 1; 128 fa[x] = r; 129 s[r][0] = x; 130 } 131 else if(k == siz) { 132 int l = getK(siz, 1, temp, 1); 133 d = ask(l, 1, temp, 1) + 1; 134 fa[x] = l; 135 s[l][1] = x; 136 } 137 else { 138 int l = getK(k, 1, temp, 1); 139 int r = getK(k + 1, 1, temp, 1); 140 int dl = ask(l, 1, temp, 1); 141 int dr = ask(r, 1, temp, 1); 142 if(dl > dr) { 143 d = dl + 1; 144 fa[x] = l; 145 s[l][1] = x; 146 } 147 else { 148 d = dr + 1; 149 fa[x] = r; 150 s[r][0] = x; 151 } 152 } 153 change(x, d, 1, temp, 1); 154 printf("%d\n", d); 155 siz++; 156 } 157 else if(f == 2) { // splay small 158 x = getK(1, 1, temp, 1); 159 int d = ask(x, 1, temp, 1); 160 if(d > 1) { 161 int r = fa[x]; 162 if(s[x][1]) { 163 fa[s[x][1]] = r; 164 } 165 s[r][0] = s[x][1]; 166 add(r, temp, 1, 1, temp, 1); 167 change(x, 1, 1, temp, 1); 168 fa[x] = 0; 169 s[x][1] = rt; 170 fa[rt] = x; 171 rt = x; 172 } 173 printf("%d\n", d); 174 } 175 else if(f == 3) { 176 x = getK(siz, 1, temp, 1); 177 int d = ask(x, 1, temp, 1); 178 if(d > 1) { 179 int l = fa[x]; 180 if(s[x][0]) { 181 fa[s[x][0]] = l; 182 } 183 s[l][1] = s[x][0]; 184 add(1, l, 1, 1, temp, 1); 185 change(x, 1, 1, temp, 1); 186 fa[x] = 0; 187 s[x][0] = rt; 188 fa[rt] = x; 189 rt = x; 190 } 191 printf("%d\n", d); 192 } 193 else if(f == 4) { 194 x = getK(1, 1, temp, 1); 195 int d = ask(x, 1, temp, 1); 196 if(d > 1) { 197 int r = fa[x]; 198 if(s[x][1]) { 199 fa[s[x][1]] = r; 200 } 201 s[r][0] = s[x][1]; 202 add(1, r - 1, -1, 1, temp, 1); 203 } 204 else { 205 add(1, temp, -1, 1, temp, 1); 206 rt = s[x][1]; 207 fa[s[x][1]] = 0; 208 } 209 change(x, -1, 1, temp, 1); 210 printf("%d\n", d); 211 siz--; 212 } 213 else if(f == 5) { 214 x = getK(siz, 1, temp, 1); 215 int d = ask(x, 1, temp, 1); 216 if(d > 1) { 217 int l = fa[x]; 218 if(s[x][0]) { 219 fa[s[x][0]] = l; 220 } 221 s[l][1] = s[x][0]; 222 add(l + 1, temp, -1, 1, temp, 1); 223 } 224 else { 225 add(1, temp, -1, 1, temp, 1); 226 rt = s[x][0]; 227 fa[s[x][0]] = 0; 228 } 229 change(x, -1, 1, temp, 1); 230 printf("%d\n", d); 231 siz--; 232 } 233 } 234 return 0; 235 }
AC代碼

洛谷P3721 單旋