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 }
View Code

 常数大概是线段树的3-4倍

又用数组写了一发

  1 // File Name: poj3468.sz.cpp
  2 // Author: darkdream
  3 // Created Time: 2014年11月07日 星期五 08时45分48秒
  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 #define keytree ch[ch[root][1]][0]
 28 struct SplayTree{
 29    int sz[maxn];   //大小
 30    int ch[maxn][2];  //儿子
 31    int pre[maxn]; //父亲
 32    int root ,top1,top2; 
 33    int ss[maxn],que[maxn];
 34    inline void Rotate(int x ,int f){
 35        int y = pre[x];
 36        push_down(y);
 37        push_down(x);
 38        ch[y][!f] = ch[x][f]; 
 39        pre[ch[x][f]] = y ; 
 40        pre[x] = pre[y];
 41        if(pre[x])
 42            ch[pre[y]][ch[pre[y]][1] == y] = x; 
 43        ch[x][f] = y ; 
 44        pre[y] = x; 
 45        push_up(y);
 46    }
 47    void Splay(int x, int goal){
 48       push_down(x);
 49       while(pre[x] != goal){
 50          if(pre[pre[x]] == goal){
 51             Rotate(x,ch[pre[x]][0] == x);
 52          }else{
 53             int y = pre[x],z = pre[y];
 54             int f = (ch[z][0] == y);
 55             if(ch[y][f] == x)
 56             {
 57                 Rotate(x,!f),Rotate(x,f);
 58             }else{
 59                 Rotate(y,f),Rotate(x,f);
 60             }
 61          }
 62       }
 63       push_up(x);
 64       if(goal == 0 ) root = x; 
 65    }
 66    void Rotateto(int k ,int goal)
 67    {
 68       int x = root; 
 69       push_down(x);
 70       while(sz[ch[x][0]] != k){
 71          if(k < sz[ch[x][0]])
 72          {
 73              x= ch[x][0];
 74          }else {
 75              k -=(sz[ch[x][0]]+1);
 76              x = ch[x][1];
 77          }
 78          push_down(x);
 79       }
 80       Splay(x,goal);
 81    }
 82    /*void erase(int x ){
 83        int father = pre[x];
 84        int head = 0 , tail = 0 ; 
 85        for()
 86        }*/
 87    void debug(){printf("%d\n",root);Treaval(root);}
 88    void Treaval(int x) {
 89        if(x) {
 90            Treaval(ch[x][0]);
 91            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d sum = %3lld\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x],sum[x]);
 92            Treaval(ch[x][1]);
 93        }
 94    }
 95    void newnode(int &x,int c)
 96    {
 97       if(top2) x= ss[--top2];
 98       else x = ++ top1;
 99       ch[x][0] = ch[x][1] = pre[x] = 0 ; 
100       sz[x] = 1;  
101       
102       val[x] = sum[x] = c;
103       add[x] = 0 ; 
104    }
105    void push_down(int x){
106      if(add[x]){
107         val[x] += add[x];
108         add[ch[x][0]] += add[x];
109         add[ch[x][1]] += add[x];
110         sum[ch[x][0]] += (long long)sz[ch[x][0]] * add[x];
111         sum[ch[x][1]] += (long long)sz[ch[x][1]] * add[x];
112         add[x] = 0 ;
113      }
114    }
115    void push_up(int x){
116       sz[x] = 1 + sz[ch[x][0]] +sz[ch[x][1]];
117 
118       sum[x] = add[x] + val[x] + sum[ch[x][0]] + sum[ch[x][1]];
119    }
120    void build(int &x,int l ,int r,int f)
121    {
122       if(l > r ) return;
123       int m = (l + r) >> 1; 
124       newnode(x,num[m]);
125       build(ch[x][0],l,m-1,x);
126       build(ch[x][1],m+1,r,x); //这里与线段树不同,因为这个节点本身就含有信息
127       pre[x] = f;
128       push_up(x);
129    }
130    void init(int n)
131    {
132        ch[0][0] = ch[0][1] = pre[0] = sz[0] =0 ; 
133        add[0] = sum[0] =0 ; 
134        root = top1 = 0 ; 
135        newnode(root,-1); //这里注意 root 是从1 开始的
136        //printf("%d\n",top1);
137        
138        newnode(ch[root][1],-1);
139        pre[top1] = root ; 
140        sz[root] = 2;
141        for(int i = 1;i <= n;i ++)
142            scanf("%d",&num[i]);
143        build(keytree,1,n,ch[root][1]);
144        push_up(ch[root][1]);
145        push_up(root);
146    }
147    void update()
148    {
149      int l , r, c; 
150      scanf("%d %d %d",&l,&r,&c);
151      Rotateto(l-1,0);
152      Rotateto(r+1,root);
153      add[keytree] += c ; 
154      sum[keytree] += (long long)sz[keytree] * c; 
155    }
156    void query()
157    {
158      int l , r; 
159      scanf("%d %d",&l,&r);
160      Rotateto(l-1,0);
161      Rotateto(r+1,root);
162      printf("%lld\n",sum[keytree]);
163    }
164    int num[maxn];
165    int val[maxn];
166    int add[maxn];
167    long long sum[maxn];
168 }sp; 
169 int main(){
170    int n , m ; 
171    scanf("%d %d",&n,&m);
172    sp.init(n);
173    while(m--)
174    {
175       char op[10];
176       scanf("%s",op);
177       if(op[0] == 'Q')
178       {
179         sp.query();
180       }else {
181         sp.update();
182       }
183       //sp.debug();
184    }
185 return 0;
186 }
View Code

 

转载于:https://www.cnblogs.com/zyue/p/4080393.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值