POJ3468 本来是一道线段树

// 然而博主用 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 }
时间: 2024-07-29 17:14:47

POJ3468 本来是一道线段树的相关文章

【POJ3468】【zkw线段树】A Simple Problem with Integers

Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. In

HDU 1754 I Hate It(线段树之单点更新,区间最值)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 70863    Accepted Submission(s): 27424 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的

bzoj 1858 序列操作(线段树)

题外话 本来想练练线段树的,然后发现这题及其蛋疼,要打一坨标记,这是我写过的最长的线段树了= = 然后我很SB的把R打成了r调了一个下午真是蛋疼QvQ Description: 给定一个0/1序列,有如下5个操作: 0:区间赋值为0 1:区间赋值为1 2:区间取反 3:询问区间内1的个数 4:询问区间内最大连续1的个数 Solution 没有操作4这显然就是个SB题,有了操作4我们需要打几个标记 我们需要从左端点开始连续0/1的个数,从右端点开始的连续0/1个数 区间内0/1个数,区间内最大连续

HDU 4578 Transformation --线段树,好题

题意: 给一个序列,初始全为0,然后有4种操作: 1. 给区间[L,R]所有值+c 2.给区间[L,R]所有值乘c 3.设置区间[L,R]所有值为c 4.查询[L,R]的p次方和(1<=p<=3) 解法: 线段树,维护三个标记,addmark,mulmark,setmark分别表示3种更新,然后p[1],p[2],p[3]分别表示该节点的1,2,3次方和.标记传递顺序setmark一定是第一个,因为setmark可以使mulmark,addmark都失效还原,mulmark和addmark的顺

南阳理工 题目9:posters(离散化+线段树)

posters 时间限制:1000 ms  |  内存限制:65535 KB 难度:6 描述 The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally deci

[题解]线段树专题测试2017.1.21

很单纯的一道线段树题.稍微改一下pushDown()就行了. Code(线段树模板竟然没超100行) 1 #include<iostream> 2 #include<sstream> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<cctype> 8 #include<queue> 9

3110: [Zjoi2013]K大数查询 树状数组套线段树

3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1384  Solved: 629[Submit][Status] Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M接下来M行,每行形如1 a b c或2 a b

HDU 1754--I Hate It(线段树基础)

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 44820    Accepted Submission(s): 17591 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f