码迷,mamicode.com
首页 > 其他好文 > 详细

POJ3468 本来是一道线段树

时间:2015-07-24 23:54:55      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

// 然而博主用 Splay Tree 做的,4000+ ms。。。飘过

  1 #include "cstdio"
  2 using namespace std;
  3 long long in[100010];
  4 const int INF = 1 << 28;
  5 
  6 struct Node {
  7     Node *pre, *ch[2];
  8     long long sz, val;
  9     long long sum, add;
 10 } *null, *root, buf[100010];
 11 int idx;
 12 
 13 Node *usdNode[100010];
 14 int top;
 15 
 16 inline void PushDown(Node *p)
 17 {
 18     if (p == null) {
 19         return ;
 20     }
 21     if(p->add) {
 22         p->sum += p->add * p->sz;
 23         p->val += p->add;
 24         if(p->ch[0] != null) {
 25             p->ch[0]->add += p->add;
 26         }
 27         if(p->ch[1] != null) {
 28             p->ch[1]->add += p->add;
 29         }
 30         p->add = 0;
 31     }
 32 }
 33 
 34 inline void Update(Node *p)
 35 {
 36     if (p == null) {
 37         return ;
 38     }
 39     PushDown(p);
 40     PushDown(p->ch[0]);
 41     PushDown(p->ch[1]);
 42     p->sz = p->ch[0]->sz + p->ch[1]->sz + 1;
 43     p->sum = p->ch[0]->sum + p->ch[1]->sum + p->val;
 44 }
 45 
 46 Node *AddNode(int val)
 47 {
 48     Node *p;
 49     if (top) {
 50         p = usdNode[top];
 51         --top;
 52     } else {
 53         ++idx;
 54         p = &buf[idx];
 55     }
 56     p->pre = p->ch[0] = p->ch[1] = null;
 57     p->sz = 1, p->val = val;
 58 
 59     p->add = 0;
 60     p->sum = val;
 61     return p;
 62 }
 63 
 64 void Init()
 65 {
 66     idx = top = 0;
 67     null = AddNode(-INF);
 68     null->sz = 0;
 69     null->sum = 0;
 70     root = AddNode(-INF);
 71 
 72     root->sum = 0;
 73     Node *p;
 74 
 75     p = AddNode(-INF);
 76     p->sum = 0;
 77 
 78     root->ch[1] = p;
 79     p->pre = root;
 80     Update(root->ch[1]);
 81     Update(root);
 82 }
 83 
 84 void Rotate(Node *p, bool c)
 85 {
 86     Node *f = p->pre;
 87     PushDown(f);
 88     PushDown(p);
 89     f->ch[!c] = p->ch[c];
 90     if (p->ch[c] != null) {
 91         p->ch[c]->pre = f;
 92     }
 93     p->pre = f->pre;
 94     if (f->pre != null) {
 95         if (f->pre->ch[0] == f) {
 96             f->pre->ch[0] = p;
 97         } else {
 98             f->pre->ch[1] = p;
 99         }
100     }
101     p->ch[c] = f;
102     f->pre = p;
103     if (f == root) {
104         root = p;
105     }
106     Update(f);
107 }
108 
109 void Splay(Node *p, Node *tf)
110 {
111     Node *f, *ff;
112     PushDown(p);
113     while (p->pre != tf) {
114         f = p->pre, ff = f->pre;
115         if (ff == tf) {
116             Rotate(p, p->pre->ch[0] == p);
117         } else {
118             if (ff->ch[0] == f) {
119                 if (f->ch[0] == p) {
120                     Rotate(f, 1);
121                     Rotate(p, 1);
122                 } else {
123                     Rotate(p, 0);
124                     Rotate(p, 1);
125                 }
126             } else {
127                 if (f->ch[1] == p) {
128                     Rotate(f, 0);
129                     Rotate(p, 0);
130                 } else {
131                     Rotate(p, 1);
132                     Rotate(p, 0);
133                 }
134             }
135         }
136         Update(p);
137     }
138 }
139 
140 Node *Build(int l, int r)
141 {
142     if (l > r) {
143         return null;
144     }
145     int mid = (l + r) >> 1;
146     Node *p = AddNode(in[mid]);
147     p->ch[0] = Build(l, mid - 1);
148     if (p->ch[0] != null) {
149         p->ch[0]->pre = p;
150     }
151     p->ch[1] = Build(mid + 1, r);
152     if (p->ch[1] != null) {
153         p->ch[1]->pre = p;
154     }
155     Update(p);
156     return p;
157 }
158 
159 Node *Select(int kth)
160 {
161     int tmp;
162     Node *p = root;
163     while (1) {
164         PushDown(p);
165         tmp = p->ch[0]->sz;
166         if (tmp + 1 == kth) {
167             break;
168         }
169         if (kth <= tmp) {
170             p = p->ch[0];
171         } else {
172             kth -= tmp + 1;
173             p = p->ch[1];
174         }
175     }
176     return p;
177 }
178 
179 void SegAdd(int pos, int tot, long long delte)
180 {
181     Splay(Select(pos - 1), null);
182     Splay(Select(pos + tot), root);
183     if (root->ch[1]->ch[0] != null) {
184         root->ch[1]->ch[0]->add += delte;
185         Splay(root->ch[1]->ch[0], null);
186     }
187 }
188 
189 void GetSum(int pos, int tot)
190 {
191     Splay(Select(pos - 1), null);
192     Splay(Select(pos + tot), root);
193     printf("%lld\n",root->ch[1]->ch[0]->sum);
194 }
195 
196 int N, Q;
197 char cmd[10];
198 
199 int main()
200 {
201     int i;
202     scanf("%d%d", &N, &Q);
203     Init();
204     for(i = 1; i <= N; ++i) {
205         scanf("%lld", &in[i]);
206     }
207     Node *tRoot = Build(1, N);
208     root->ch[1]->ch[0] = tRoot;
209     tRoot->pre = root->ch[1];
210     Update(root->ch[1]);
211     Update(root);
212 
213     int l, r;
214     long long c;
215     while(Q--) {
216         scanf("%s", cmd);
217         switch(cmd[0]) {
218         case Q:
219             scanf("%d%d", &l, &r);
220             GetSum(l + 1, r - l + 1);
221             break;
222         case C:
223             scanf("%d%d%lld", &l, &r, &c);
224             SegAdd(l + 1, r - l + 1, c);
225         }
226     }
227 }

 

POJ3468 本来是一道线段树

标签:

原文地址:http://www.cnblogs.com/AC-Phoenix/p/4674992.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!