POJ3468/splay树/成段更新

板子题,正在努力看懂板子。。

http://blog.csdn.net/acm_cxlove/article/details/7815019

http://www.cnblogs.com/kuangbin/archive/2013/04/21/3034081.html

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4
  5 #define keyTree (ch[ ch[root][1] ][0])
  6 #define LL long long
  7
  8 using namespace std;
  9
 10 const int maxn = 222222;
 11
 12 struct SpalyTree{
 13     int sz[maxn];
 14     int ch[maxn][2];
 15     int pre[maxn];
 16     int root,top1,top2;
 17     int ss[maxn], que[maxn];
 18
 19     void Rotate(int x,int f)
 20     {
 21         int y = pre[x];
 22         push_down(y);
 23         push_down(x);
 24         ch[y][!f] = ch[x][f];
 25         pre[ ch[x][f]] = y;
 26         pre[x] = pre[y];
 27         if(pre[x]) ch[pre[y] ][ch[pre[y]][1]==y ] = x;
 28         ch[x][f] = y;
 29         pre[y] = x;
 30         push_up(y);
 31     }
 32     void Splay(int x,int goal)
 33     {
 34         push_down(x);
 35         while(pre[x] != goal)
 36         {
 37             if(pre[pre[x] ] == goal)
 38             {
 39                 Rotate(x,ch[pre[x] ][0] == x);
 40             }
 41             else
 42             {
 43                 int y = pre[x],z = pre[y];
 44                 int f = (ch[z][0] == y);
 45                 if(ch[y][f] == x)
 46                 {
 47                     Rotate(x,!f),Rotate(x,f);
 48                 }
 49                 else
 50                 {
 51                     Rotate(y,f),Rotate(x,f);
 52                 }
 53             }
 54         }
 55         push_up(x);
 56         if(goal == 0) root = x;
 57     }
 58     void RotateTo(int k,int goal)
 59     {
 60         int x = root;
 61         push_down(x);
 62         while(sz[ ch[x][0] ] != k)
 63         {
 64             if(k < sz[ ch[x][0] ])
 65             {
 66                 x = ch[x][0];
 67             }
 68             else
 69             {
 70                 k -= (sz[ch[x][0] ] + 1);
 71                 x = ch[x][1];
 72             }
 73             push_down(x);
 74         }
 75         Splay(x,goal);
 76     }
 77     void erase(int x)
 78     {
 79         int father = pre[x];
 80         int head = 0,tail = 0;
 81         for(que[tail++] = x;head < tail;head++)
 82         {
 83             ss[top2++] = que[head];
 84             if(ch[que[head] ][0]) que[tail++] = ch[que[head] ][0];
 85             if(ch[que[head] ][1]) que[tail++] = ch[que[head] ][1];
 86         }
 87         ch[father ][ch[father][1]==x ] = 0;
 88         push_up(father);
 89     }
 90     void debug(){printf("%d\n",root);Treaval(root);}
 91     void Treaval(int x)
 92     {
 93         if(x)
 94         {
 95             Treaval(ch[x][0]);
 96             printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
 97             Treaval(ch[x][1]);
 98         }
 99     }
100     void NewNode(int &x,int c)
101     {
102         if(top2) x = ss[--top2];
103         else x = ++top1;
104         ch[x][0] = ch[x][1] = pre[x] = 0;
105         sz[x] = 1;
106
107         val[x] = sum[x] = c;
108         add[x] = 0;
109     }
110     void push_down(int x)
111     {
112         if(add[x])
113         {
114             val[x] += add[x];
115             add[ch[x][0] ] += add[x];
116             add[ch[x][1] ] += add[x];
117             sum[ch[x][0] ] += (LL)sz[ch[x][0] ]*add[x];
118             sum[ch[x][1] ] += (LL)sz[ch[x][1] ]*add[x];
119             add[x] = 0;
120         }
121     }
122     void push_up(int x)
123     {
124         sz[x] = 1+sz[ch[x][0] ] + sz[ch[x][1] ];
125         sum[x] = add[x] + val[x] + sum[ch[x][0] ] + sum[ch[x][1] ];
126     }
127     void makeTree(int &x,int l,int r,int f)
128     {
129         if(l > r) return ;
130         int m = (l+r)>>1;
131         NewNode(x,num[m]);
132         makeTree(ch[x][0],l,m-1,x);
133         makeTree(ch[x][1],m+1,r,x);
134         pre[x] = f;
135         push_up(x);
136     }
137     void init(int n)
138     {
139         ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
140         add[0] = sum[0] = 0;
141
142         root = top1 = 0;
143         NewNode(root, -1);
144         NewNode(ch[root][1],-1);
145         pre[top1] = root;
146         sz[root] = 2;
147
148         for(int i=0;i<n;i++)
149             scanf("%d",&num[i]);
150         makeTree(keyTree,0,n-1,ch[root][1]);
151         push_up(ch[root][1]);
152         push_up(root);
153     }
154     void update()
155     {
156         int l,r,c;
157         scanf("%d%d%d",&l,&r,&c);
158         RotateTo(l-1,0);
159         RotateTo(r+1,root);
160         add[keyTree] += c;
161         sum[keyTree] += (LL)c*sz[keyTree];
162     }
163     void query()
164     {
165         int l,r;
166         scanf("%d%d",&l,&r);
167         RotateTo(l-1,0);
168         RotateTo(r+1,root);
169         printf("%lld\n",sum[keyTree]);
170     }
171
172     int num[maxn];
173     int val[maxn];
174     int add[maxn];
175     LL  sum[maxn];
176 }spt;
177
178 int n,m;
179
180 int main()
181 {
182     while(~scanf("%d%d",&n,&m))
183     {
184         spt.init(n);
185         char op[2];
186         for(int i=0;i<m;i++)
187         {
188             scanf("%s",op);
189             if(op[0] == ‘Q‘)
190             {
191                 spt.query();
192             }
193             else
194                 spt.update();
195         }
196     }
197 }
时间: 2024-10-09 20:08:47

POJ3468/splay树/成段更新的相关文章

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

POJ 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种. 很明显的线段树成段更新,但是查询却不好弄.经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,....假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6).那我们就把

POJ 2528 Mayor&#39;s posters (hash+线段树成段更新)

题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW.后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报.现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报?(PS:看见一部分也算看到.) 思路:简单的成段更新,但是数据量是1千万,会MT,所以要区间压缩(离散化),保证覆盖的关系不变,离散化的时候有个易错的细节,poj数据水了,这个易错点引用h

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是

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

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 77486   Accepted: 23862 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 【线段树-成段更新】

题目: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值

poj3468A Simple Problem with Integers(线段树+成段更新)

题目链接: huangjing题意: 给n个数,然后有两种操作. [1]Q a b 询问a到b区间的和. [2]C a b c将区间a到b的值都增加c. 思路: 线段树成段更新的入门题目..学会使用lazy即可.还需要注意的是,lazy的时候更改是累加,而不是直接修改..有可能连续几次进行修改操作..注意这一点就好了... 题目: Language: Default A Simple Problem with Integers Time Limit: 5000MS   Memory Limit:

线段树成段更新 hdu 1698 Just a Hook

题意:给出n根金属棒,和操作数q,初始时每个金属棒价值都为1,每次操作可以把从x到y的金属棒更换材质,铜为1,银为2,金为3,最后统计所有的金属棒总价值是多少. 线段树成段更新,需要用到lazy标记,所谓lazy标记就是:更新一个区间的时候不更新到底,只更新到第一个满足更新范围的区间(即范围内的最大的区间),然后给节点加上lazy标记,以后需要更新到该节点的子节点的时候,就把lazy标记转移到子节点上,这样大大提升了效率. 代码: