Splay chapter 2: POJ 3667/BZOJ 1593
据说Splay最霸气的东西是它可以搞一些其他平衡树甚至其他树不能搞得东西 比如区间的操作 至少Treap就不行(FHQ请无视蒟蒻不懂您的Treap)
同时我发现 几乎所有线段树的题 Splay都能搞(但大部分属于自残行为) 所以我就去做了一道 USACO FEB08 的 经典题 真是够呛
Problem:
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 8116 | Accepted: 3447 |
Description
The cows are journeying north to Thunder Bay in Canada to gain cultural enrichment and enjoy a vacation on the sunny shores of Lake Superior. Bessie, ever the competent travel agent, has named the Bullmoose Hotel on famed Cumberland Street as their vacation residence. This immense hotel has N (1 ≤ N ≤ 50,000) rooms all located on the same side of an extremely long hallway (all the better to see the lake, of course).
The cows and other visitors arrive in groups of size Di (1 ≤ Di ≤ N) and approach the front desk to check in. Each group i requests a set of Di contiguous rooms from Canmuu, the moose staffing the counter. He assigns them some set of consecutive room numbers r..r+Di-1 if they are available or, if no contiguous set of rooms is available, politely suggests alternate lodging. Canmuu always chooses the value of r to be the smallest possible.
Visitors also depart the hotel from groups of contiguous rooms. Checkout i has the parameters Xi and Di which specify the vacating of rooms Xi ..Xi +Di-1 (1 ≤ Xi ≤ N-Di+1). Some (or all) of those rooms might be empty before the checkout.
Your job is to assist Canmuu by processing M (1 ≤ M < 50,000) checkin/checkout requests. The hotel is initially unoccupied.
Input
* Line 1: Two space-separated integers: N and M
* Lines 2..M+1: Line i+1 contains request expressed as one of two possible formats: (a) Two space separated integers representing a check-in request: 1 and Di (b) Three space-separated integers representing a check-out: 2, Xi, and Di
Output
* Lines 1.....: For each check-in request, output a single line with a single integer r, the first room in the contiguous sequence of rooms to be occupied. If the request cannot be satisfied, output 0.
Sample Input
10 6 1 3 1 3 1 3 1 3 2 5 5 1 6
Sample Output
1 4 7 0 5
Source
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <iostream> 7 #define rep(i,l,r) for(int i=l;i<=r;++i) 8 using namespace std; 9 const int oo = ~0U>>2; 10 int n,m,a,b,cmd; 11 class Splay{ 12 private: 13 struct Node{ 14 int key,cnt; 15 int lsum,rsum,sum,mark,size; 16 bool v; 17 Node *c[2],*fa; 18 Node(int _key,Node *_fa){ 19 key = _key; fa = _fa; v = true; mark = size = 0; 20 lsum = rsum = sum = cnt = 1; c[0] = c[1] = NULL; 21 } 22 inline int ll() {return c[0] ? c[0]->lsum : 0;} 23 inline int lr() {return c[0] ? c[0]->rsum : 0;} 24 inline int rl() {return c[1] ? c[1]->lsum : 0;} 25 inline int rr() {return c[1] ? c[1]->rsum : 0;} 26 inline int ls() {return c[0] ? c[0]->sum : 0;} 27 inline int rs() {return c[1] ? c[1]->sum : 0;} 28 inline int lsz() {return c[0] ? c[0]->size : 0;} 29 inline int rsz() {return c[1] ? c[1]->size : 0;} 30 }; 31 Node *root; 32 inline void upd(Node *tag){ 33 if(!tag) return; 34 tag->size = tag->cnt + tag->lsz() + tag->rsz(); 35 tag->lsum = tag->ll(); 36 if(tag->lsum == tag->lsz() && tag->v) 37 tag->lsum += 1 + tag->rl(); 38 tag->rsum = tag->rr(); 39 if(tag->rsum == tag->rsz() && tag->v) 40 tag->rsum += 1 + tag->lr(); 41 tag->sum = max(tag->ls(),tag->rs()); 42 if(tag->v) tag->sum = max(tag->sum,tag->lr() + 1 + tag->rl()); 43 } 44 inline void push_down(Node *tag){ 45 if(!tag || !tag->mark) return; 46 int val = tag->mark > 0 ? 1 : 0; 47 tag->lsum = tag->rsum = tag->sum = val * tag->size; tag->v = val; 48 if(tag->c[0]) tag->c[0]->mark = tag->mark; 49 if(tag->c[1]) tag->c[1]->mark = tag->mark; 50 tag->mark = 0; 51 } 52 inline void zig(Node *tag,int d){ 53 Node *f = tag->fa; 54 int anti = 1 - d; 55 push_down(tag->c[0]); push_down(tag->c[1]); push_down(f->c[anti]); 56 f->c[d] = tag->c[anti]; 57 if(f->c[d]) 58 f->c[d]->fa = f; 59 tag->fa = f->fa; 60 if(f->fa->c[0] == f) 61 f->fa->c[0] = tag; 62 else 63 f->fa->c[1] = tag; 64 tag->c[anti] = f; 65 f->fa = tag; 66 upd(f); 67 } 68 inline int f(Node *tag){ 69 return tag->fa->c[1] == tag; 70 } 71 inline void splay(Node *tag,Node *goal){ 72 push_down(tag); 73 while(tag->fa != goal){ 74 if(tag->fa->fa == goal) 75 zig(tag,f(tag)); 76 else{ 77 if(f(tag->fa) == f(tag)) 78 zig(tag->fa,f(tag->fa)),zig(tag,f(tag)); 79 else 80 zig(tag,f(tag)),zig(tag,f(tag)); 81 } 82 } 83 upd(tag); 84 } 85 inline Node *search(int key,int &d){ 86 Node *tag = root->c[0],*tmp = root; d = 0; 87 push_down(tag); 88 while(tag && tag->key != key){ 89 if(tag->key < key) tmp = tag,tag = tag->c[1]; 90 else tmp = tag,tag = tag->c[0]; 91 push_down(tag); 92 } 93 return tag ? tag : tmp; 94 } 95 inline int ask(int l,Node *tag){ 96 if(!tag) return 0; 97 push_down(tag); push_down(tag->c[0]); push_down(tag->c[1]); 98 if(tag->sum < l) return 0; 99 if(tag->ls() >= l) return ask(l,tag->c[0]); 100 if(tag->v){ 101 if(tag->lr() + 1 + tag->rl() >= l) 102 if(tag->lr()) return tag->key - tag->lr(); 103 else return tag->key; 104 } 105 return ask(l,tag->c[1]); 106 } 107 public: 108 Splay() { 109 root = new Node(19960628,NULL); Node *tmp = new Node(0,root); Node *tmp2 = new Node(oo,tmp); 110 root->c[0] = tmp; tmp->sum = tmp->lsum = tmp->rsum = tmp->v = tmp->cnt = 0; 111 tmp->c[1] = tmp2; tmp2->sum = tmp2->lsum = tmp2->rsum = tmp2->v = tmp2->cnt = 0; 112 } 113 void ready(int n){ 114 Node *tag; int d; 115 splay(tag = search(0,d),root); splay(search(oo,d),tag); 116 rep(i,1,n){ 117 Node *f = search(i,d); 118 Node *tmp = new Node(i,f); 119 f->c[d] = tmp; upd(tmp); upd(f); 120 splay(tmp,root); 121 } 122 } 123 void query(int l){ 124 int tag = ask(l,root->c[0]); int d; 125 if(!tag) {printf("0\n"); return;} 126 Node *L = search(tag - 1,d); Node *R = search(tag + l <= n ? tag + l : oo,d); 127 splay(L,root); splay(R,L); 128 R->c[0]->mark --; 129 splay(R->c[0],root); 130 printf("%d\n",tag); 131 } 132 void erase(int x,int l){ 133 int d; 134 Node *L = search(x - 1,d),*R = search(x + l <= n ? x + l : oo,d); 135 splay(L,root); splay(R,L); 136 R->c[0]->mark ++; 137 splay(R->c[0],root); 138 } 139 }tree; 140 int main() 141 { 142 freopen("input.in","r",stdin); freopen("output.out","w",stdout); 143 while(scanf("%d%d",&n,&m) != EOF){ 144 tree.ready(n); 145 rep(i,1,m){ 146 scanf("%d",&cmd); 147 if(cmd == 1){ 148 scanf("%d",&a); 149 tree.query(a); continue; 150 } 151 if(cmd == 2){ 152 scanf("%d%d",&a,&b); 153 tree.erase(a,b); continue; 154 } 155 } 156 } 157 return 0; 158 }
最后 我发现USACO的月赛 可以直接 点 http://contest.usaco.org 以后可以做做这个 完了