splay
来源:互联网 发布:淘宝直播入口电脑版 编辑:程序博客网 时间:2024/04/25 14:14
这个星期打了一些splay, 下面在这里做下总结吧。
splay 的核心 要实现的就是 把二叉排序树中的一个节点移到它的某个祖先节点的位置。
/*
这个操作初看来可能没有什么实际的用途,但是仔细思考简直是 非常方便。
当我们需要对一个区间进行操作时, 只要把这个区间的左端点的前一个点和右端点的后一个点 分别旋到 根节点和 根节点 的右儿子节点, 这时候一个感人肺腑的现象就出现了: 以根节点的右儿子节点的左儿子节点为根的这棵树就是 所询问的线段。画个图是很显然的。
有了这个操作后很多东西就都可以迎刃而解了。
其实splay比线段树好的地方大概也就是 这里, 即它对区间 的灵活性。
总结splay可以多实现的东西我目前大概只知道这三个:插入一个区间, 删除一个区间, 翻转一个区间。
*/
下面看实现,
最暴力的方法就是 把以目标节点为根的子树拆了 然后 从新 建,但是容易发现有一种更加便捷的方法就是把 当前节点一层一层地旋上去。
这里使用的是双旋, 所以分为两种情况: 父亲就是目标节点, 直接转上去就好了; 父亲不是目标节点, 根据当前节点 和当前 节点的父节点 是否同是自身父节点的左(右)儿子再分成两种情况讨论: 如果 左右性相同, 先把父节点向上转, 再把当前节点向上转; 如果左右性不同, 就把当前节点向上转两次。 (转法 不唯一, 只要可以把当前节点转到父节点的父节点就可以了)。
下面处理刚才说的那个旋转。 如果把一个点向右上旋, 当前节点右儿子的 位置肯定就会被 当前节点的父节点占领, 哪怎么办呢? 显然这里多出来了一个点就一定有一个地方少了一个点—— 原来的父节点的 左儿子 (即当前节点)现在没有了, 于是自然要把多出来的这个接上去, 考虑 二叉排序树的性质这样接时没有问题的。显然在旋转后 , 当前节点变成了原先的父节点的父节点, 变成了原先的父节点的父节点 的子节点, 所以再把这两层关系分别处理一下就好了。
以上就是splay全部的核心思想了, 具体实现时 考虑左右的对称性 可以把左旋和右旋放到一个函数里写, 一个 k 等于1时是右旋, 等于0时是左旋。
实现起来极其简单。 只有简洁优美的十几行。
void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}void rotate(int x, int k){ int y = fat[x]; jie(ch[x][k], y, !k),jie(x, fat[y], ch[fat[y]][1] == y),jie(y, x, k);}void splay(int x, int goal){ while(fat[x] != goal){ if(fat[fat[x]] == goal){rotate(x, ch[fat[x]][0] == x); break;} int y = fat[x], ky = ch[fat[y]][1] == y; if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky); else rotate(x, ky), rotate(x, !ky); } if(!goal)root = x;}
虽然splay操作真的很短, 但是考虑到简单的操作用线段树就可以了, 所以splay的题一般会出很多种操作, 分一下类就会觉得代码很长, 其实没有什么的, 也就是维护一个二叉排序树的各种性质。
先上几道可以用线段树等较简单方法实现的题来巩固对splay的理解。
hdu1754 I hate it
这道题相信没人 没有用线段树做过, 因为什么操作都没有所以用splay打也超级短啊! 短的令人想哭。
<pre style="font-family:Courier New;text-align:left;"><span style="color:blue;">#include <iostream>#include <cstdio>#define MAXN 200005</span><strong><span style="color:#0000FF;">using namespace</span></strong> std<strong><span style="color:#FF00FF;">;</span><span style="color:blue;">int</span></strong> n<strong><span style="color:#FF00FF;">,</span></strong> q<strong><span style="color:#FF00FF;">,</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">],</span></strong> root<strong><span style="color:#FF00FF;">,</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>MAXN<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">2</span><strong><span style="color:#FF00FF;">];</span><span style="color:blue;">void</span></strong> pushup<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">){</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">],</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">]],</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">]]));}</span><span style="color:blue;">void</span></strong> jie<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> y<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> k<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;">if</span><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">)</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">][</span></strong>k<strong><span style="color:#FF00FF;">] =</span></strong> x<strong><span style="color:#FF00FF;">;</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> y<strong><span style="color:#FF00FF;">;}</span><span style="color:blue;">void</span></strong> rotate<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> k<strong><span style="color:#FF00FF;">){</span><span style="color:blue;"> int</span></strong> y<strong><span style="color:#FF00FF;"> =</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">];</span></strong> jie<strong><span style="color:#FF00FF;">(</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">][</span></strong>k<strong><span style="color:#FF00FF;">],</span></strong> y<strong><span style="color:#FF00FF;">, !</span></strong>k<strong><span style="color:#FF00FF;">),</span></strong>jie<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">],</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] ==</span></strong> y<strong><span style="color:#FF00FF;">),</span></strong>jie<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">,</span></strong> x<strong><span style="color:#FF00FF;">,</span></strong> k<strong><span style="color:#FF00FF;">);</span></strong> pushup<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">);}</span><span style="color:blue;">void</span></strong> splay<strong><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> x<strong><span style="color:#FF00FF;">,</span><span style="color:blue;"> int</span></strong> goal<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;"> while</span><span style="color:#FF00FF;">(</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] !=</span></strong> goal<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;"> if</span><span style="color:#FF00FF;">(</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">]] ==</span></strong> goal<strong><span style="color:#FF00FF;">){</span></strong>rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] ==</span></strong> x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;"> break</span><span style="color:#FF00FF;">;}</span><span style="color:blue;"> int</span></strong> y<strong><span style="color:#FF00FF;"> =</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">],</span></strong> ky<strong><span style="color:#FF00FF;"> =</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>fat<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">]][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] ==</span></strong> y<strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;"> if</span><span style="color:#FF00FF;">(</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;">][</span></strong>ky<strong><span style="color:#FF00FF;">] ==</span></strong> x<strong><span style="color:#FF00FF;">)</span></strong>rotate<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">),</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;"> else</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong> ky<strong><span style="color:#FF00FF;">),</span></strong> rotate<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">, !</span></strong>ky<strong><span style="color:#FF00FF;">); }</span></strong>pushup<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;"> if</span><span style="color:#FF00FF;">(!</span></strong>goal<strong><span style="color:#FF00FF;">)</span></strong>root<strong><span style="color:#FF00FF;"> =</span></strong> x<strong><span style="color:#FF00FF;">;}</span><span style="color:blue;">int</span><span style="color:#0000FF;"> main</span><span style="color:#FF00FF;">(){</span><span style="color:#0000FF;"> while</span><span style="color:#FF00FF;">(</span></strong>scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d%d"</span><strong><span style="color:#FF00FF;">, &</span></strong>n<strong><span style="color:#FF00FF;">, &</span></strong>q<strong><span style="color:#FF00FF;">) !=</span></strong> EOF<strong><span style="color:#FF00FF;">){</span><span style="color:#0000FF;"> for</span><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> i<strong><span style="color:#FF00FF;"> =</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> <=</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> ++)</span></strong>scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d"</span><strong><span style="color:#FF00FF;">, &</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">]);</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">] = -</span></strong><span style="color:#CC3300;">100000000</span><strong><span style="color:#FF00FF;">;</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 3</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;"> for</span><span style="color:#FF00FF;">(</span><span style="color:blue;">int</span></strong> i<strong><span style="color:#FF00FF;"> =</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;">;</span></strong> i<strong><span style="color:#FF00FF;"> --){</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">; (</span></strong>i<strong><span style="color:#FF00FF;"> ==</span></strong> n<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;"> )?</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;"> :</span></strong> ch<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">1</span><strong><span style="color:#FF00FF;">] =</span></strong> i<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong> fat<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">] =</span></strong> i<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">] =</span></strong> max<strong><span style="color:#FF00FF;">(</span></strong>maxx<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">],</span></strong> num<strong><span style="color:#FF00FF;">[</span></strong>i<strong><span style="color:#FF00FF;">]); }</span></strong> root<strong><span style="color:#FF00FF;"> =</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">;</span><span style="color:#0000FF;"> while</span><span style="color:#FF00FF;">(</span></strong>q<strong><span style="color:#FF00FF;"> --){</span><span style="color:blue;"> char</span></strong> s<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">5</span><strong><span style="color:#FF00FF;">];</span><span style="color:blue;"> int</span></strong> x<strong><span style="color:#FF00FF;">,</span></strong> y<strong><span style="color:#FF00FF;">;</span></strong> scanf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%s%d%d"</span><strong><span style="color:#FF00FF;">,</span></strong> s<strong><span style="color:#FF00FF;">, &</span></strong>x<strong><span style="color:#FF00FF;">, &</span></strong>y<strong><span style="color:#FF00FF;">);</span></strong>x<strong><span style="color:#FF00FF;"> ++;</span><span style="color:#0000FF;"> if</span><span style="color:#FF00FF;">(</span></strong>s<strong><span style="color:#FF00FF;">[</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">] ==</span></strong><span style="color:green;"> 'U'</span><strong><span style="color:#FF00FF;">)</span></strong>splay<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">,</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">),</span></strong>num<strong><span style="color:#FF00FF;">[</span></strong>x<strong><span style="color:#FF00FF;">] =</span></strong> y<strong><span style="color:#FF00FF;">,</span></strong> pushup<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;">);</span><span style="color:#0000FF;"> else</span></strong> splay<strong><span style="color:#FF00FF;">(</span></strong>x<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">,</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">),</span></strong> splay<strong><span style="color:#FF00FF;">(</span></strong>y<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">,</span></strong> x<strong><span style="color:#FF00FF;"> -</span></strong><span style="color:#CC3300;"> 1</span><strong><span style="color:#FF00FF;">),</span></strong> printf<strong><span style="color:#FF00FF;">(</span></strong><span style="color:green;">"%d\n"</span><strong><span style="color:#FF00FF;">,</span></strong> maxx<strong><span style="color:#FF00FF;">[</span></strong>ch<strong><span style="color:#FF00FF;">[</span></strong>y<strong><span style="color:#FF00FF;"> +</span></strong><span style="color:#CC3300;"> 2</span><strong><span style="color:#FF00FF;">][</span></strong><span style="color:#CC3300;">0</span><strong><span style="color:#FF00FF;">]]); } }</span><span style="color:#0000FF;"> return</span></strong><span style="color:#CC3300;"> 0</span><strong><span style="color:#FF00FF;">;}</span></strong>
poj 3468 a simple promble with integers
同裸线段树经典题。多了一个修改操作。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define MAXN 100005using namespace std;int n, q, root, num[MAXN], ch[MAXN][2], fat[MAXN], r[MAXN], sz[MAXN];long long summ[MAXN];inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}inline void pushup(int x){sz[x] = sz[ch[x][1]] + sz[ch[x][0]] + 1;summ[x] = r[x] + num[x] + summ[ch[x][0]] + summ[ch[x][1]];}inline void pushdown(int x){if(!r[x])return;num[x] += r[x];r[ch[x][0]] += r[x]; r[ch[x][1]] += r[x];summ[ch[x][0]] += (long long)sz[ch[x][0]] * r[x];summ[ch[x][1]] += (long long)sz[ch[x][1]] * r[x];r[x] = 0;}inline void rotate(int x, int k){int y = fat[x]; pushdown(y); pushdown(x);jie(ch[x][k], y, !k), jie(x, fat[y], ch[fat[y]][1] == y), jie(y, x, k);pushup(y); }inline void splay(int x, int goal){pushdown(x);while(fat[x] != goal){if(fat[fat[x]] == goal){rotate(x, ch[fat[x]][0] == x); break;}int y = fat[x], ky = ch[fat[y]][1] == y;if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);else rotate(x, ky), rotate(x, !ky);} pushup(x);if(! goal)root = x;}int main(){scanf("%d%d", &n, &q);for(int i = 2; i <= n + 1; i ++)scanf("%d", &num[i]); fat[n + 2] = n + 1;for(int i = n + 1; i; i --){ch[i][1] = i + 1; summ[i] = summ[i + 1] + num[i]; sz[i] = sz[i + 1] + 1; fat[i] = i - 1;}root = 1;while(q --){char s[5]; int x, y, z; scanf("%s%d%d", s, &x, &y);x ++; y ++;if(s[0] == 'Q')splay(x - 1, 0), splay(y + 1, x - 1), cout<<summ[ch[y + 1][0]]<<endl;else{scanf("%d", &z);splay(x - 1, 0); splay(y + 1, x - 1);r[ch[y + 1][0]] += z;summ[ch[y + 1][0]] += (long long)z * sz[ch[y + 1][0]];}}return 0;}
bzoj 1588 营业额统计
所以这次又新增了一个插入操作。
#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#include <cstring>#define MAXN 100005#define INF 1<<30using namespace std;int n, num, ch[MAXN][2], a[MAXN], cnt, root, ans, fat[MAXN];void addnode(int father, int k){ a[++ cnt] = k; fat[cnt] = father;}void rotate(int x, int kind){ int f = fat[x]; ch[f][!kind] = ch[x][kind]; fat[ch[x][kind]] = f; //if(fat[f]) ch[fat[f]][ch[fat[f]][1] == f] = x; fat[x] = fat[f]; ch[x][kind] = f; fat[f] = x;}void splay(int r){ while(fat[r]){ if(!fat[fat[r]]){rotate(r, ch[fat[r]][1] != r); continue;} int f = fat[r]; int kindf = ch[fat[f]][1] == f; if(ch[f][kindf] == r)rotate(f, !kindf), rotate(r, !kindf); else rotate(r, kindf), rotate(r, !kindf); } root = r;}int insert(int k){ int r = root; while(ch[r][a[r] < k]){ if(a[r] == k){splay(r); return 0;} r = ch[r][a[r] < k]; } ch[r][a[r] < k] = cnt + 1; addnode(r, k); splay(cnt); return 1;}int get(int x, int k){ int tmp = ch[x][!k]; if(!tmp)return INF; while(ch[tmp][k])tmp = ch[tmp][k]; return abs(a[tmp] - a[x]);}int main(){ //freopen("1588.in", "r", stdin); scanf("%d%d", &n, &num); root = 1; addnode(0, num); ans += num; for(int i = 2; i <= n; i ++){ num = 0; scanf("%d", &num); if(! insert(num))continue; ans += min(get(root, 0), get(root, 1)); }cout<<ans<<endl; return 0;}
bzoj1503 郁闷的出纳员
所以这次又新增了删除操作。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define MAXN 200005using namespace std;int n, minn, minn0, x, sz[MAXN], ch[MAXN][2], pre[MAXN], cnt[MAXN], val[MAXN], summ, rt, top;inline void pushup(int x){sz[x] = cnt[x] + sz[ch[x][0]] + sz[ch[x][1]];}inline void jie(int y, int x, int k){if(y)ch[y][k] = x; pre[x] = y;}inline void rotate(int x, int k){ int y = pre[x];jie(y, ch[x][k], !k); jie(pre[y], x, ch[pre[y]][1] == y); jie(x, y, k); pushup(y);}inline void splay(int x, int goal){ while(pre[x] != goal){ if(pre[pre[x]] == goal){rotate(x, ch[pre[x]][0] == x); break;} int y = pre[x], kf = ch[pre[y]][1] == y; if(ch[y][kf] == x)rotate(y, !kf), rotate(x, !kf); else rotate(x, kf), rotate(x, !kf); } pushup(x); if(!goal)rt = x;}inline void newnode(int &x, int c){ x = ++ top; sz[x] = 1; cnt[x] = 1; val[x] = c; }inline void insert(int &x, int key, int f){ if(!x){ newnode(x, key); pre[x] = f; splay(x, 0); return; } if(key == val[x]){ cnt[x] ++; sz[x] ++; splay(x, 0); return ; } if(key < val[x])insert(ch[x][0], key, x); else insert(ch[x][1], key, x); pushup(x);}inline void del(int &x, int f){ if(!x)return; if(val[x] >= minn) del(ch[x][0], x); else{ summ += sz[ch[x][0]] + cnt[x]; x = ch[x][1]; pre[x] = f; if(f == 0)rt = x; del(x, f); } if(x)pushup(x);}inline int findk(int x, int k){//cout<<x<<endl; if(k < sz[ch[x][0]] + 1)return findk(ch[x][0], k); if(k > sz[ch[x][0]] + cnt[x])return findk(ch[x][1], k - sz[ch[x][0]] - cnt[x]); splay(x, 0); return val[x]; }int main(){ scanf("%d%d", &n, &minn); minn0 = minn; char s[10]; int k; while(n --){ scanf("%s%d", s, &k); if(s[0] == 'A')minn -= k; if(s[0] == 'S'){ minn += k; if(sz[rt])del(rt, 0); } if(s[0] == 'I' && k >= minn0)insert(rt, k + minn - minn0, 0); if(s[0] == 'F'){ if(k > sz[rt])puts("-1"); else printf("%d\n", findk(rt, sz[rt] - k + 1) - minn + minn0); } }cout<<summ<<endl; return 0; }
bzoj1798 维护序列
这时候有了修改操作, 自然要用到懒标记, 懒标记的pushup 和pushdown和线段树基本相同。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define MAXN 100005using namespace std;int n, p, la, a, b, c;struct Tree{ int l, r;long long plus, mul, summ;}tree[MAXN * 4];inline void pushup(int t){tree[t].summ = (tree[t + t].summ + tree[t + t + 1].summ) % p;}inline void pushdown(int t){ tree[t + t].plus = (tree[t + t].plus * tree[t].mul + tree[t].plus) % p; tree[t + t + 1].plus = (tree[t + t + 1].plus * tree[t].mul + tree[t].plus) % p; tree[t + t].mul = tree[t + t].mul * tree[t].mul % p; tree[t + t + 1].mul = tree[t + t + 1].mul * tree[t].mul % p; tree[t + t].summ = (tree[t + t].summ * tree[t].mul + tree[t].plus * (tree[t + t].r - tree[t + t].l + 1)) % p; tree[t + t + 1].summ = (tree[t + t + 1].summ * tree[t].mul + tree[t].plus * (tree[t + t + 1].r - tree[t + t + 1].l + 1)) % p; tree[t].plus = 0; tree[t].mul = 1;}void build(int l, int r, int t){ tree[t].l = l; tree[t].r = r; tree[t].plus = 0; tree[t].mul = 1; if(l == r){scanf("%lld", &tree[t].summ); return;} int mid = l + r >> 1; build(l, mid, t + t); build(mid + 1, r, t + t + 1); pushup(t);}void alter(int t, int l, int r){ if(tree[t].l >= l && tree[t].r <= r){ if(la == 1){ tree[t].plus = tree[t].plus * c % p; tree[t].mul = tree[t].mul * c % p; tree[t].summ = tree[t].summ * c % p; }else{ tree[t].plus = (tree[t].plus + c) % p; tree[t].summ = (tree[t].summ + (long long)c * (tree[t].r - tree[t].l + 1)) % p; } return; }pushdown(t); int mid = tree[t].l + tree[t].r >> 1; if(mid >= l)alter(t + t, l, r); if(mid < r)alter(t + t + 1, l, r); pushup(t);}long long query(int t, int l, int r){ if(tree[t].l >= l && tree[t].r <= r){ return tree[t].summ % p; }pushdown(t); int mid = tree[t].l + tree[t].r >> 1;long long cnt = 0; if(mid >= l)cnt = query(t + t, l, r); if(mid < r)cnt += query(t + t + 1, l, r); pushup(t); return cnt % p;}int main(){ scanf("%d%d", &n, &p); build(1, n, 1); int m; scanf("%d", &m); while(m --){ scanf("%d%d%d", &la, &a, &b); if(la != 3){scanf("%d", &c); alter(1, a, b); }else{ printf("%lld\n", query(1, a, b)); } } return 0;}
bzoj1500 维修数列
这道题要处理的东西有点多, 但实际上每一个小模块都是之前写过的, 只是把它们整合在一起而已。
易错点: 1, 在转移的时候要判左右儿子是否为空(我开始是想不去特判而给空的节点赋一个很小的值什么的, 但都不好实现)
2, 垃圾回收避免MLE。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#define MAXN 510005#define INF 1<<30using namespace std;int n, m, root, cnt, fat[MAXN], ch[MAXN][2], sz[MAXN], summ[MAXN], lmax[MAXN], rmax[MAXN], maxx[MAXN], num[MAXN], a[MAXN];bool rev[MAXN], change[MAXN];queue<int>q;void newnode(int &x, int fatt, int val){ if(!q.empty())x = q.front(), q.pop(); else x = ++ cnt; fat[x] = fatt; ch[x][0] = ch[x][1] = rev[x] = change[x] = 0; sz[x] = 1; summ[x] = lmax[x] = rmax[x] = maxx[x] = num[x] = val;}inline void pushdown(int x){ if(!x)return; if(rev[x]){ rev[x] = 0; if(ch[x][0])rev[ch[x][0]] ^= 1; if(ch[x][1])rev[ch[x][1]] ^= 1; swap(ch[x][0], ch[x][1]); swap(lmax[x], rmax[x]); } if(change[x]){ change[x] = 0; if(ch[x][0]){ change[ch[x][0]] = 1; num[ch[x][0]] = num[x]; summ[ch[x][0]] = num[x] * sz[ch[x][0]]; rmax[ch[x][0]] = lmax[ch[x][0]] = maxx[ch[x][0]] = max(num[x], summ[ch[x][0]]); } if(ch[x][1]){ change[ch[x][1]] = 1; num[ch[x][1]] = num[x]; summ[ch[x][1]] = num[x] * sz[ch[x][1]]; rmax[ch[x][1]] = lmax[ch[x][1]] = maxx[ch[x][1]] = max(num[x], summ[ch[x][1]]); } }}inline void pushup(int x){ if(!x)return; pushdown(ch[x][0]), pushdown(ch[x][1]); summ[x] = (ch[x][0] ? summ[ch[x][0]] : 0) + (ch[x][1] ? summ[ch[x][1]] : 0) + num[x]; sz[x] = (ch[x][0] ? sz[ch[x][0]] : 0) + (ch[x][1] ? sz[ch[x][1]] : 0) + 1; lmax[x] = max(ch[x][0] ? lmax[ch[x][0]] : num[x], (ch[x][0] ? summ[ch[x][0]] : 0) + num[x] + max(0, ch[x][1] ? lmax[ch[x][1]] : 0)); rmax[x] = max(ch[x][1] ? rmax[ch[x][1]] : num[x], (ch[x][1] ? summ[ch[x][1]] : 0) + num[x] + max(0, ch[x][0] ? rmax[ch[x][0]] : 0)); maxx[x] = max(max(ch[x][0] ? maxx[ch[x][0]] : num[x], ch[x][1] ? maxx[ch[x][1]] : num[x]), max(0, ch[x][0] ? rmax[ch[x][0]] : 0) + max(0, ch[x][1] ? lmax[ch[x][1]] : 0) + num[x]);}void build(int &x, int l, int r, int fat){ if(l <= r){ int mid = l + r >> 1; //cout<<mid<<endl; //cout<<a[mid]<<endl; newnode(x, fat, a[mid]); if(l == r)return; if(mid > l)build(ch[x][0], l, mid - 1, x); build(ch[x][1], mid + 1, r, x); pushup(x); }}inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}inline void rotate(int x, int k){ int y = fat[x];pushdown(y);//pushdown(x); jie(ch[x][k], y, !k); jie(x, fat[y], ch[fat[y]][1] == y); jie(y, x, k); pushup(y);}void splay(int x, int goal){ if(x == goal)return; pushdown(x); while(fat[x] != goal){ if(fat[fat[x]] == goal){ // pushdown(fat[x]); // pushdown(x); rotate(x, ch[fat[x]][0] == x); break; } // pushdown(fat[fat[x]]); // pushdown(fat[x]); // pushdown(x); int y = fat[x], ky = ch[fat[y]][1] == y; if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky); else rotate(x, ky), rotate(x, !ky); }pushup(x); if(!goal)root = x;}int select(int k){ int x = root; pushdown(x); while(sz[ch[x][0]] + 1 != k){ if(sz[ch[x][0]] + 1 < k){ k -= sz[ch[x][0]] + 1; x = ch[x][1]; } else x = ch[x][0]; pushdown(x); }return x;}void Reverse(int a, int b){ int A = select(a), B = select(b + 2); splay(A, 0), splay(B, A); rev[ch[B][0]] ^= 1; pushup(B), pushup(A);}int Get_sum(int a, int b){ int A = select(a), B = select(b + 2); splay(A, 0), splay(B, A); return summ[ch[B][0]]; }void del(int x){ if(!x)return; q.push(x); del(ch[x][0]); del(ch[x][1]);}void Delete(int a, int b){ int A = select(a), B = select(b + 2); splay(A, 0), splay(B, A); del(ch[B][0]); ch[B][0] = 0; pushup(B), pushup(A);}int Max_sum(){ int A = select(1), B = select(sz[root]); splay(A, 0), splay(B, A); return maxx[ch[B][0]];}void Make_same(int a, int b, int c){ int A = select(a), B = select(b + 2); splay(A, 0), splay(B, A); int x = ch[B][0]; change[x] = 1; num[x] = c; summ[x] = c * sz[x]; rmax[x] = lmax[x] = maxx[x] = max(c, summ[x]); pushup(B), pushup(A);}void Insert(int a, int b){a ++; int A = select(a), B = select(a + 1); splay(A, 0), splay(B, A); // printf("!! %d %d\n", summ[ch[ch[root][1]][0]], summ[root]); build(ch[ch[root][1]][0], 1, b, ch[root][1]); pushup(ch[root][1]); pushup(root);// printf("!! %d %d\n", summ[ch[ch[root][1]][0]], summ[root]);}int main(){// freopen("sequence.in", "r", stdin);// freopen("sequence.out", "w", stdout); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++)scanf("%d", &a[i]); newnode(root, 0, -10000); newnode(ch[root][1], root, -10000); sz[root] ++; build(ch[ch[root][1]][0], 1, n, ch[root][1]); pushup(ch[root][1]); pushup(root); // for(int i = 1; i <= 15; i ++)printf("%d %d %d %d\n", i, num[i], lmax[i], maxx[i]); char s[30]; int aa, bb, cc, dd, ee; while(m --){scanf("%s", s); // cout<<"!!!!"<<endl; // printf("!! %s", s); if(s[0] == 'R'){ scanf("%d%d", &aa, &bb); Reverse(aa, aa + bb - 1); } if(s[0] == 'G'){ scanf("%d%d", &aa, &bb); // cout<<"######"<<endl; printf("%d\n", Get_sum(aa, aa + bb - 1)); } if(s[0] == 'D'){ scanf("%d%d", &aa, &bb); n -= bb; Delete(aa, aa + bb - 1); } if(s[0] == 'M' && s[2] == 'X'){ // cout<<"!!!!"<<endl; printf("%d\n", Max_sum()); } if(s[0] == 'M' && s[2] == 'K'){ scanf("%d%d%d", &aa, &bb, &cc); Make_same(aa, aa + bb - 1, cc); } if(s[0] == 'I'){ scanf("%d%d", &aa, &bb); n += bb; for(int i = 1; i <= bb; i ++)scanf("%d", &a[i]); Insert(aa, bb); } // printf("%d\n", Get_sum(1, n)); /* int pre; pre = 0; for(int i = 1; i <= sz[root]; i ++){ splay(select(i), pre); pre = select(i); }*/// for(int i = sz[root]; i >= 1; i --)printf("%d %d %d %d\n", maxx[select(i)], ch[select(i)][0], ch[select(i)][1], num[select(i)]); } return 0;}
bzoj 1208 宠物收养所
还是特别简单的一道裸题。
就是一个支持插入, 删除, 询问前驱和后继的splay。
我第一次在对 INF 操作的时候忘记了会爆int, 所以WA 了一次, 这种错误是在以后必须避免的。
12.11 : 我下面的这个代码虽然可以A但是是错的, 应该再 特判 要删除的那个节点是不是 在最开始建出来的虚点, 因为这是早年的题所以数据比较水。。
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#define MAXN 80005#define INF (1<<31) - 1using namespace std;int n, ans, flag = -1, fat[MAXN], ch[MAXN][2], root, a[MAXN], cntt, now;inline void jie(int x, int y, int k){if(y)ch[y][k] = x; fat[x] = y;}inline void rotate(int x, int k){int y = fat[x];jie(ch[x][k], y, !k), jie(x, fat[y], ch[fat[y]][1] == y), jie(y, x, k);}void splay(int x, int goal){if(x == goal)return;while(fat[x] != goal){if(fat[fat[x]] == goal){rotate(x, ch[fat[x]][0] == x); break;}int y = fat[x], ky = ch[fat[y]][1] == y;if(ch[y][ky] == x)rotate(y, !ky), rotate(x, !ky);else rotate(x, ky), rotate(x, !ky);} if(goal == 0)root = x;}void newnode(int &x, int ff, int c){x = ++ cntt, a[cntt] = c, fat[cntt] = ff; }void insert(int x){int r = root;while(ch[r][a[r] < x])r = ch[r][a[r] < x];newnode(ch[r][a[r] < x], r, x);splay(cntt, 0);}int pre(int x){ int tmp = ch[x][0];if(!tmp)return 1;while(ch[tmp][1])tmp = ch[tmp][1]; return tmp;}int hou(int x){int tmp = ch[x][1];if(!tmp)return 2;while(ch[tmp][0])tmp = ch[tmp][0]; return tmp;}void del(int x){int pree = pre(x), houu = hou(x);splay(pree, 0), splay(houu, root);ch[houu][0] = 0;}void work(int x){insert(x); splay(cntt, 0);int pree = pre(cntt), houu = hou(cntt);int tmp = abs((long long)a[pree] - x) <= abs((long long)a[houu] - x) ? pree : houu;ans += abs(a[tmp] - x); ans %= 1000000;del(root);//printf("%d %d\n", a[pree], a[houu]);splay(tmp, 0); del(tmp);}int main(){newnode(root, 0, INF + 1), newnode(ch[root][1], root, INF);scanf("%d", &n);while(n --){int k, c; scanf("%d%d", &k, &c);if(flag == -1 || flag == k)insert(c), now ++, flag = k;else work(c), now --;if(!now)flag = -1;}cout<<ans<<endl;return 0;}
bzoj 1507 editor
- SPLAY
- splay
- splay
- splay
- Splay
- Splay
- splay
- splay
- splay
- splay
- Splay
- splay
- Splay
- splay
- Splay
- Splay
- splay
- Splay大功告成
- Java多线程的理解
- Cracking the coding interview--Q8.1
- 摄像头显示OpenCV或DirectShow
- Java String类型剖析及其JVM内存分配详解
- ftp服务器搭建
- splay
- ZAM 3D入门教程(2):场景编辑器
- IOS开发---C语言-⑤流程控制:顺序结构、选择结构、循环结构
- MVC设计模式-QStringListModel
- 排队游戏
- IOS 代码签名包括证书,配置文件和私钥
- ZAM 3D入门教程(3):Viewport
- Warning: mysql_fetch_assoc() expects parameter 1 to be resource解决方法
- mysql如何做order by