POJ 3468 A Simple Problem with Integers splay

题意:给你一个数列,区间更新和区间询问

解题思路:splay指针版撸的,4700 ms险过

解题代码:

  1 // File Name: spoj3468.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年11月05日 星期三 19时40分26秒
  4
  5 #include<vector>
  6 #include<list>
  7 #include<map>
  8 #include<set>
  9 #include<deque>
 10 #include<stack>
 11 #include<bitset>
 12 #include<algorithm>
 13 #include<functional>
 14 #include<numeric>
 15 #include<utility>
 16 #include<sstream>
 17 #include<iostream>
 18 #include<iomanip>
 19 #include<cstdio>
 20 #include<cmath>
 21 #include<cstdlib>
 22 #include<cstring>
 23 #include<ctime>
 24 #define LL long long
 25 #define maxn 100010
 26 using namespace std;
 27 int num[maxn];
 28 struct Splaynode{
 29      struct node{
 30         struct node *pre,*ch[2];
 31         LL add;
 32         LL sum;
 33         LL val;
 34         LL size;
 35      }*root;
 36      node *newnode(int c)
 37      {
 38         node * p = (node*)malloc(sizeof(node));
 39         p->pre = p->ch[0] = p->ch[1] = NULL;
 40         p->sum = p->val = c ;
 41         p->size = 1 ;
 42         p->add = 0 ;
 43         return p ;
 44      }
 45      void push_down(node *x)
 46      {
 47         //printf("push_down***%lld\n",x->val);
 48         x->val += x->add;
 49         if(x->ch[0] != NULL)
 50         {
 51            x->ch[0]->sum += x->ch[0]->size * x->add;
 52            x->ch[0]->add += x->add;
 53         }
 54         if(x->ch[1] != NULL)
 55         {
 56            x->ch[1]->sum += x->ch[1]->size * x->add;
 57            x->ch[1]->add += x->add;
 58         }
 59         x->add = 0 ;
 60      }
 61      void push_up(node *x)
 62      {
 63         x->size = 1;
 64         x->sum = x->val + x->add;
 65         if(x->ch[0] != NULL)
 66         {
 67            x->size += x->ch[0]->size;
 68            x->sum += x->ch[0]->sum;
 69         }
 70         if(x->ch[1] != NULL)
 71         {
 72            x->size += x->ch[1]->size;
 73            x->sum += x->ch[1]->sum;
 74         }
 75      }
 76      void print(node *x)
 77      {
 78          if(x == NULL)
 79              return;
 80          print(x->ch[0]);
 81          printf("%lld(%lld) ",x->val,x->sum);
 82          print(x->ch[1]);
 83          push_up(x);
 84      }
 85      void build(node *&x ,int l , int r ,node *f) //这里需要传递一个引用
 86      {
 87      //  printf("%d %d\n",l,r);
 88        if(l > r )
 89            return ;
 90        int m = (l + r )  >> 1;
 91        x = newnode(num[m]);
 92        build(x->ch[0],l,m-1,x);
 93        build(x->ch[1],m+1,r,x);
 94        x->pre = f ;
 95        push_up(x);
 96      }
 97      void init(int n)
 98      {
 99        root = NULL;
100        root = newnode(-1);
101        root->ch[1]=newnode(-1);
102        root->ch[1]->pre = root;
103        root->size = 2;
104        for(int i = 1;i <= n;i ++)
105          scanf("%d",&num[i]);
106        build(root->ch[1]->ch[0],1,n,root->ch[1]);
107        push_up(root->ch[1]);
108        push_up(root);
109      }
110      void Rotate(node *x ,int c)
111      {
112        node *y = x->pre;
113        //printf("%lld %lld\n",y->val,x->val);
114        push_down(y);
115        push_down(x);
116        y->ch[!c] = x->ch[c];
117        if(x->ch[c] != NULL)  x->ch[c]->pre = y;
118        x->pre = y->pre;
119        if(y->pre != NULL)
120        {
121            if(y->pre->ch[0] == y) y->pre->ch[0] = x ;
122            else y->pre->ch[1] = x ;
123        }
124        x->ch[c] = y,y->pre = x;
125        push_up(y);
126      }
127      void Delete(node *x)
128      {
129          if(x == NULL)
130              return;
131          Delete(x->ch[0]);
132          Delete(x->ch[1]);
133          //printf("%lld\n",x->val);
134          free(x);
135          x = NULL;
136          if(x != NULL)
137              printf("****\n");
138          //x = NULL;
139          //printf("%lld\n",x->val);
140      }
141      void Splay(node *x ,node *f)
142      {
143        //printf("****\n");
144        push_down(x); //为何要push_down
145       // printf("****\n");
146        for(; x->pre != f ;)
147          if(x ->pre->pre == f)
148          {
149              if(x->pre-> ch[0] == x)
150                 Rotate(x,1);
151              else Rotate(x,0);
152          }else{
153             node *y = x->pre ,*z = y ->pre;
154             if(z->ch[0] == y)
155             {
156                 if(y->ch[0] == x)
157                     Rotate(y,1),Rotate(x,1);
158                 else Rotate(x,0),Rotate(x,1);
159             }else{
160                 if(y->ch[1] == x)
161                     Rotate(y,0),Rotate(x,0);
162                 else
163                     Rotate(x,1),Rotate(x,0);
164             }
165          }
166        push_up(x);
167        if(f == NULL) root = x;
168      }
169      void Rotateto(int k ,node *goal)
170      {
171          node *x  = root;
172          push_down(x);
173          while(1)
174          {
175             if((x->ch[0] == NULL &&k == 0) || (x->ch[0]!= NULL && x->ch[0]->size == k))
176                 break;
177             if(x->ch[0] !=NULL && k < x->ch[0]->size)
178             {
179                 x = x->ch[0];
180             }else{
181                 k -= ((!x->ch[0])?1:x->ch[0]->size+1);
182                 x = x->ch[1];
183             }
184             push_down(x);
185    //        printf("%lld %lld %d\n",x->val,x->size,k);
186          }
187         // printf("****\n");
188          //printf("%lld\n",x->pre->val);
189          Splay(x,goal);
190      }
191      void update()
192      {
193         int l , r, c;
194         scanf("%d %d %d",&l,&r,&c);
195         Rotateto(l-1,NULL);
196         Rotateto(r+1,root);
197         root->ch[1]->ch[0]->add += c;
198         root->ch[1]->ch[0]->sum += root->ch[1]->ch[0]->size * c;
199      }
200      void query()
201      {
202        int l , r;
203        scanf("%d %d",&l,&r);
204        Rotateto(l-1,NULL);
205     //   print(root);
206       // printf("\n");
207        Rotateto(r+1,root);
208       // print(root);
209       // printf("\n");
210       // printf("****\n");
211        printf("%lld\n",root->ch[1]->ch[0]->sum);
212      }
213
214 }sp;
215
216 int main(){
217     int n ,m;
218     scanf("%d %d",&n,&m);
219     sp.init(n);
220     //sp.print(sp.root);;
221 //    printf("\n");
222     while(m--)
223     {
224        char op[10];
225        scanf("%s",op);
226        if(op[0] == ‘Q‘)
227        {
228           sp.query();
229        }else {
230           sp.update();
231        }
232     }
233 //    while()
234     return 0;
235 }

时间: 2024-08-09 18:48:31

POJ 3468 A Simple Problem with Integers splay的相关文章

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

POJ 3468 A Simple Problem with Integers 【树状数组】

题目链接:http://poj.org/problem?id=3468 题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c. 完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时. 换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对. 假设数组sum[i]为原数组从v[1]到v[i]的和,数

POJ 3468 A Simple Problem with Integers(详细题解)

这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传. 这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询. Inc往下带的过程也是区

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

线段树(成段更新) POJ 3468 A Simple Problem with Integers

题目传送门 1 /* 2 线段树-成段更新:裸题,成段增减,区间求和 3 注意:开long long:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 using namespace std; 11 12 #define lson l, mid, rt <<

POJ - 3468 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

poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

题目链接 题意: 只有这两种操作 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. 分析:自己写的有点麻烦了,写的时候手残+脑残,改了好久. val+lazy*(r-l+1)表示和,如果lazy==0表示当前区间加的值不统一. 1 #include <iostream