【POJ2761】【fhq treap】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.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.
The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of Aa, Aa+1, ... , Ab.
Output
You need to answer all Q commands in order. One answer in a line.
Sample Input
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4
Sample Output
4 55 9 15
Hint
The sums may exceed the range of 32-bit integers.
Source
POJ Monthly--2007.11.25, Yang Yi
【分析】
这个其实是个水题。我只是拿来fhq treap的...
Orzzzzzz范大爷
这种数据结构真是...能保证treap的性质同时也能保证合并后的树还能原封不动的切出来...
说它是treap,我觉得就一个fix像treap而已。
这个数据结构的精髓在合并和分裂(和打标记?)。有注释.
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #include <utility> 7 #include <iomanip> 8 #include <string> 9 #include <cmath> 10 #include <queue> 11 #include <assert.h> 12 #include <map> 13 #include <ctime> 14 #include <cstdlib> 15 #define LOCAL 16 const int MAXN = 100000 + 10; 17 const int INF = 0x3f3f3f3f; 18 const int SIZE = 450; 19 const int maxnode = 1101000; 20 using namespace std; 21 typedef long long ll; 22 ll n, m; 23 struct fhqTreap{ 24 struct Node{ 25 Node *l, *r; 26 ll delta, sum; 27 ll size, fix, val; 28 }*root, *null, mem[1101000]; 29 ll tot; 30 31 ll BIG_RAND(){return (ll)rand()*RAND_MAX + (ll)rand();} 32 void init(){ 33 tot = 0; 34 NEW(null, 0); 35 null->size = 0; 36 root = null; 37 insert(0, n);//插入 38 } 39 void update(Node *t){ 40 if (t == null) return; 41 t->size = t->l->size + t->r->size + 1; 42 t->sum = t->val; 43 if (t->l != null) t->sum += t->l->sum; 44 if (t->r != null) t->sum += t->r->sum; 45 } 46 //标记下传=-= 47 void push_down(Node *t){ 48 if (t->delta){ 49 t->val += t->delta; 50 51 if (t->l != null) {t->l->delta += t->delta, t->l->sum += t->l->size * t->delta;} 52 if (t->r != null) {t->r->delta += t->delta, t->r->sum += t->r->size * t->delta;} 53 54 t->delta = 0; 55 } 56 } 57 58 void NEW(Node *&t, ll val){ 59 t = &mem[tot++]; 60 t->size = 1; 61 t->fix = BIG_RAND(); 62 t->sum = t->val = val; 63 t->delta = 0; 64 t->l = t->r = null; 65 } 66 //将t分裂为大小p和t->size - p的两个子树 67 void split(Node *t, Node *&a, Node *&b, int p){ 68 if (t->size <= p) a = t, b = null; 69 else if (p == 0) a = null, b = t; 70 else { 71 push_down(t); 72 if (t->l->size >= p){ 73 b = t; 74 split(t->l, a , b->l, p); 75 update(b); 76 }else{ 77 a = t; 78 split(t->r, a->r, b, p - t->l->size - 1); 79 update(a); 80 } 81 } 82 } 83 //将a,b树合并为t 84 void merge(Node *&t, Node *a, Node *b){ 85 if (a == null) t = b; 86 else if (b == null) t = a; 87 else { 88 if (a->fix > b->fix){//按fix值排序 89 push_down(a); 90 t = a; 91 merge(t->r, a->r, b); 92 }else{ 93 push_down(b); 94 t = b; 95 merge(t->l, a, b->l); 96 } 97 update(t); 98 } 99 } 100 void add(ll l, ll r, ll val){ 101 Node *a, *b, *c; 102 split(root, a, b, l - 1); 103 split(b, b, c, r - l + 1); 104 b->delta += val; 105 b->sum += val * b->size; 106 merge(a, a, b); 107 merge(root, a, c); 108 } 109 ll query(ll l, ll r){ 110 Node *a, *b, *c; 111 split(root, a, b, l - 1); 112 split(b, b, c, r - l + 1); 113 ll ans = b->sum; 114 merge(b, b, c); 115 merge(root, a, b); 116 return ans; 117 } 118 //把b挤出去 119 void Delete(ll p){ 120 Node *a, *b, *c; 121 split(root, a, b, p - 1); 122 split(b, b, c, 1); 123 merge(root, a, c); 124 } 125 Node *Insert(ll x){//不可思议的插入方式 126 if (x == 0) return null; 127 if (x == 1){ 128 ll tmp; 129 scanf("%lld", &tmp); 130 Node *a; 131 NEW(a, tmp); 132 return a; 133 } 134 Node *a, *b; 135 int mid = x / 2; 136 a = Insert(mid); 137 b = Insert(x - mid); 138 merge(a, a, b); 139 return a; 140 } 141 142 //在pos处插入x个数字 143 void insert(ll pos, ll x){ 144 Node *a, *b, *c, *t; 145 //跟块状链表的有点像,分裂再合并 146 split(root, a, b, pos); 147 c = Insert(x);//插入一个值为x的树 148 merge(a, a, c); 149 merge(root, a, b); 150 } 151 }A; 152 153 void work(){ 154 char str[3]; 155 while (m--){ 156 scanf("%s", str); 157 if (str[0] == 'Q'){ 158 ll l, r; 159 scanf("%lld%lld", &l, &r); 160 printf("%lld\n", A.query(l, r)); 161 }else{ 162 ll l, r, k; 163 scanf("%lld%lld%lld", &l, &r, &k); 164 A.add(l, r, k); 165 } 166 } 167 } 168 169 int main(){ 170 171 while( scanf("%lld%lld", &n, &m) != EOF){ 172 A.init(); 173 work(); 174 } 175 return 0; 176 }