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

0 0
原创粉丝点击