【POJ2761】【fhq treap】A Simple Problem with Integers

Description

You have N integers, A1A2, ... , 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 A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.
Each of the next Q lines represents an operation.
"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q a b" means querying the sum of AaAa+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

【分析】
这个其实是个水题。我只是拿来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 }
View Code

 

posted @ 2015-03-11 10:23  TCtower  阅读(226)  评论(0编辑  收藏  举报