Splay小结

有关论文:

运用伸展树解决数列维护问题

算法合集之《伸展树的基本操作与应用》

splay的伸展操作 splay(x,goal)将x节点移到goal节点的下方,通过左旋和右旋基本操作实现,其实现过程在论文中有详细介绍。

对于用splay去维护一个数列,有以下常用操作。

1.splay(x,goal) 将结点k旋转到goal结点的下方

2.getpos(x) 查询第x个节点的在树中的位置。

3.rotateto(x,goal) 将第x个结点旋转到goal结点下方,可以由 rotateto(x,goal) = splay(getpos(x),goal)得到

4.插入操作,在L,R之间插入一个区间或者一个数,先rotateto(L-1,0),然后rotateto(R+1,root),把L-1旋转到根结点,把R+1旋转到根节点的右儿子结点上,然后插入的东西插入在根的右儿子的左儿子结点上,这样就保证插入的数据夹在L,R之间,为了防止L-1,R-1越界,可以添加两个无用结点。

5.删除操作,同上。

6.翻转操作,将区间[L,R]翻转,可以先和插入操作进行同样的处理,先把L,R 区间 夹在 L-1和R+1结点之间,然后对关键节点打上翻转标记(懒惰标记),类似线段树。

下面贴上HH的splay模板:

/*

http://acm.pku.edu.cn/JudgeOnline/problem?id=3468

区间跟新,区间求和
*/
#include <cstdio>
#define keyTree (ch[ ch[root][1] ][0])
const int maxn = 222222;
struct SplayTree{
    int sz[maxn];
    int ch[maxn][2];
    int pre[maxn];
    int root , top1 , top2;
    int ss[maxn] , que[maxn];

    inline void Rotate(int x,int f) {
        int y = pre[x];
        push_down(y);
        push_down(x);
        ch[y][!f] = ch[x][f];
        pre[ ch[x][f] ] = y;
        pre[x] = pre[y];
        if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
        ch[x][f] = y;
        pre[y] = x;
        push_up(y);
    }
    inline void Splay(int x,int goal) {
        push_down(x);
        while(pre[x] != goal) {
            if(pre[pre[x]] == goal) {
                Rotate(x , ch[pre[x]][0] == x);
            } else {
                int y = pre[x] , z = pre[y];
                int f = (ch[z][0] == y);
                if(ch[y][f] == x) {
                    Rotate(x , !f) , Rotate(x , f);
                } else {
                    Rotate(y , f) , Rotate(x , f);
                }
            }
        }
        push_up(x);
        if(goal == 0) root = x;
    }
    inline void RotateTo(int k,int goal) {//把第k位的数转到goal下边
        int x = root;
        push_down(x);
        while(sz[ ch[x][0] ] != k) {
            if(k < sz[ ch[x][0] ]) {
                x = ch[x][0];
            } else {
                k -= (sz[ ch[x][0] ] + 1);
                x = ch[x][1];
            }
            push_down(x);
        }
        Splay(x,goal);
    }
    inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存
        int father = pre[x];
        int head = 0 , tail = 0;
        for (que[tail++] = x ; head < tail ; head ++) {
            ss[top2 ++] = que[head];
            if(ch[ que[head] ][0]) que[tail++] = ch[ que[head] ][0];
            if(ch[ que[head] ][1]) que[tail++] = ch[ que[head] ][1];
        }
        ch[ father ][ ch[father][1] == x ] = 0;
        pushup(father);
    }
    //以上一般不修改//////////////////////////////////////////////////////////////////////////////
    void debug() {printf("%d\n",root);Treaval(root);}
    void Treaval(int x) {
        if(x) {
            Treaval(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d\n",x,ch[x][0],ch[x][1],pre[x],sz[x],val[x]);
            Treaval(ch[x][1]);
        }
    }
    //以上Debug

    //以下是题目的特定函数:
    inline void NewNode(int &x,int c) {
        if (top2) x = ss[--top2];//用栈手动压的内存池
        else x = ++top1;
        ch[x][0] = ch[x][1] = pre[x] = 0;
        sz[x] = 1;

        val[x] = sum[x] = c;/*这是题目特定函数*/
        add[x] = 0;
    }

    //把延迟标记推到孩子
    inline void push_down(int x) {/*这是题目特定函数*/
        if(add[x]) {
            val[x] += add[x];
            add[ ch[x][0] ] += add[x];
            add[ ch[x][1] ] += add[x];
            sum[ ch[x][0] ] += (long long)sz[ ch[x][0] ] * add[x];
            sum[ ch[x][1] ] += (long long)sz[ ch[x][1] ] * add[x];
            add[x] = 0;
        }
    }
    //把孩子状态更新上来
    inline void push_up(int x) {
        sz[x] = 1 + sz[ ch[x][0] ] + sz[ ch[x][1] ];
        /*这是题目特定函数*/
        sum[x] = add[x] + val[x] + sum[ ch[x][0] ] + sum[ ch[x][1] ];
    }

    /*初始化*/
    inline void makeTree(int &x,int l,int r,int f) {
        if(l > r) return ;
        int m = (l + r)>>1;
        NewNode(x , num[m]);        /*num[m]权值改成题目所需的*/
        makeTree(ch[x][0] , l , m - 1 , x);
        makeTree(ch[x][1] , m + 1 , r , x);
        pre[x] = f;
        push_up(x);
    }
    inline void init(int n) {/*这是题目特定函数*/
        ch[0][0] = ch[0][1] = pre[0] = sz[0] = 0;
        add[0] = sum[0] = 0;

        root = top1 = 0;
        //为了方便处理边界,加两个边界顶点
        NewNode(root , -1);
        NewNode(ch[root][1] , -1);
        pre[top1] = root;
        sz[root] = 2;

        for (int i = 0 ; i < n ; i ++) scanf("%d",&num[i]);
        makeTree(keyTree , 0 , n-1 , ch[root][1]);
        push_up(ch[root][1]);
        push_up(root);
    }
    /*更新*/
    inline void update( ) {/*这是题目特定函数*/
        int l , r , c;
        scanf("%d%d%d",&l,&r,&c);
        RotateTo(l-1,0);
        RotateTo(r+1,root);
        add[ keyTree ] += c;
        sum[ keyTree ] += (long long)c * sz[ keyTree ];
    }
    /*询问*/
    inline void query() {/*这是题目特定函数*/
        int l , r;
        scanf("%d%d",&l,&r);
        RotateTo(l-1 , 0);
        RotateTo(r+1 , root);
        printf("%lld\n",sum[keyTree]);
    }

    /*这是题目特定变量*/
    int num[maxn];
    int val[maxn];
    int add[maxn];
    long long sum[maxn];
}spt;

int main() {
    int n , m;
    scanf("%d%d",&n,&m);
    spt.init(n);
    while(m --) {
        char op[2];
        scanf("%s",op);
        if(op[0] == ‘Q‘) {
            spt.query();
        } else {
            spt.update();
        }
    }
    return 0;
}

NOI2005维修序列,囊括的splay的基本操作,要使用内存池回收内存

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]
const int maxn = 500005 + 20;
int ch[maxn][2], Size[maxn];
int pre[maxn], val[maxn], sum[maxn], lsum[maxn], rsum[maxn], Max[maxn], colorall[maxn], colorrev[maxn], a1[maxn];
int que[maxn];
int top2;
int ss[maxn];
int tot, root;
int pos;
const int INF = -1e9;

void update_same(int r, int v)
{
    if (!r) return;
    colorall[r] = 1;
    val[r] = v;
    sum[r] = Size[r] * v;
    lsum[r] = rsum[r] = Max[r] = max(v, sum[r]);
}

void update_rev(int  r)
{
    if (!r) return;
    swap(ch[r][0], ch[r][1]);
    swap(lsum[r], rsum[r]);
    colorrev[r] ^= 1;
}
void newnode(int &x, int fa, int key)
{
    //x = ++tot;
    if (top2) x = ss[top2--];
    else x = ++tot;
    pre[x] = fa; Size[x] = 1; val[x] = key; sum[x] = key; lsum[x] = rsum[x] = Max[x] = key;
    ch[x][0] = ch[x][1] = 0;
    colorrev[x] = 0;  colorall[x] = 0;
}

void up(int x)
{
    int l = ch[x][0]; int r = ch[x][1];
    Size[x] = Size[l] + Size[r] + 1;
    sum[x] = sum[l] + sum[r] + val[x];
    lsum[x] = max(lsum[l], sum[l] + val[x] + max(0, lsum[r]));
    rsum[x] = max(rsum[r], sum[r] + val[x] + max(0, rsum[l]));
    Max[x] = max(0, rsum[l]) + val[x] + max(0, lsum[r]);
    Max[x] = max(Max[l], max(Max[r], Max[x]));
}

void down(int r)
{
    if (colorrev[r]) {
        update_rev(ch[r][0]);
        update_rev(ch[r][1]);
        colorrev[r] = 0;
    }
    if (colorall[r]) {
        update_same(ch[r][0], val[r]);
        update_same(ch[r][1], val[r]);
        colorall[r] = 0;
    }
}

void build(int &x, int fa, int l, int r)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, a1[mid]);
    build(ch[x][0], x, l, mid - 1);
    build(ch[x][1], x, mid + 1, r);
    up(x);
}
void init(int n)
{
    tot = top2 = root = 0;
    Size[0] = colorrev[0] = pre[0] = ch[0][0] = ch[0][1] = val[0] = sum[0] = colorall[0] = 0;
    lsum[0] = rsum[0] = Max[0] = INF;
    newnode(root, 0, -1);
    newnode(ch[root][1], root, -1);
//    up(root);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a1[i]);
    }
    build(keytree, ch[root][1], 0, n - 1); //傻逼了 ch[root][1] 变成root了
//    up(ch[root][1]); up(root);
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            //down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    return r;
}
void erase(int x) {
    if (!x) return;
    ss[++top2] = x;
    erase(ch[x][0]); erase(ch[x][1]);
}

void rotateto(int x, int y)
{
    int t = getpos(x);
    splay(t, y);
}

void Delete(int pos, int k)
{
    int ll = pos - 1; int rr = pos + k;
    rotateto(ll, 0); rotateto(rr, root);
    erase(keytree);
    pre[keytree] = 0; keytree = 0;
    //up(ch[root][1]);
    //up(root);
}

void insert(int pos, int k)
{
    rotateto(pos, 0);
    rotateto(pos + 1, root);  //这样插会变快
    for (int i = 0; i < k; i++) scanf("%d", &a1[i]);
    build(keytree, ch[root][1], 0, k-1);
    //up(ch[root][1]);
    //up(root);
}

void updateall(int pos, int k, int c)
{
    int ll = pos - 1; int rr = pos + k;
    rotateto(ll, 0); rotateto(rr, root);
    update_same(keytree, c);
    //up(ch[root][1]);
    //up(root);
}

void rev(int pos, int k)
{
    int ll = pos - 1; int rr = pos + k;
    rotateto(ll, 0);
    rotateto(rr, root);
    update_rev(keytree);
}

void  asksum(int pos, int k)
{
    int ll = pos - 1; int rr = pos + k;
    rotateto(ll, 0);
    rotateto(rr, root);
    printf("%d\n", sum[keytree]);
}

void askmax()
{
    splay(1, 0); splay(2, root);
    printf("%d\n", Max[keytree]);
}

int main()
{
    int n, m, a, b, c;
    char str[20];
    while (scanf("%d%d", &n, &m) != EOF) {
        init(n);
        while (m--) {
            scanf("%s", str);
            if (str[0] == ‘M‘&&str[2] == ‘X‘) {
                askmax();
                continue;
            }
            if (str[0] == ‘I‘) {
                scanf("%d%d", &a, &b);
                insert(a, b);
            }
            if (str[0] == ‘D‘) {
                scanf("%d%d", &a, &b);
                Delete(a, b);
            }
            if (str[0] == ‘M‘) {
                scanf("%d%d%d", &a, &b, &c);
                updateall(a, b, c);
            }
            if (str[0] == ‘R‘) {
                scanf("%d%d", &a, &b);
                rev(a, b);
            }
            if (str[0] == ‘G‘) {
                scanf("%d%d", &a, &b);
                asksum(a, b);
            }
        }
    }
    return 0;
}

HDU4453 Looploop 12年杭州

一些splay的常用操作,注意循环取余和结点翻转后更新指针位置,注释中有

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include <fstream>
using namespace std;
typedef long long LL;
#define keytree ch[ ch[root][1]][0]
inline bool scanf_(int &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0; //EOF
    while (c != ‘-‘ && (c<‘0‘ || c>‘9‘)) c = getchar();
    sgn = (c == ‘-‘) ? -1 : 1;
    ret = (c == ‘-‘) ? 0 : (c - ‘0‘);
    while (c = getchar(), c >= ‘0‘&&c <= ‘9‘) ret = ret * 10 + (c - ‘0‘);
    ret *= sgn;
    return 1;
}

inline void printf_(int x) {
    if (x>9) printf_(x / 10);
    putchar(x % 10 + ‘0‘);
}

const int maxn = 5e5 + 20;

int tot, root;
int pre[maxn], coloradd[maxn], colorrev[maxn], Size[maxn], val[maxn], ch[maxn][2];
int pos, n;
int a[maxn];

void newnode(int &x, int fa, int key)
{
    x = ++tot;
    pre[x] = fa;
    val[x] = key;
    Size[x] = 1;
    ch[x][0] = ch[x][1] = 0;
    coloradd[x] = 0; colorrev[x] = 0;
}

void downadd(int rt, int add)
{
    if (rt == 0) return;
    val[rt] += add;
    coloradd[rt] += add;
}
void downrev(int rt)
{
    if (rt == 0) return;
    swap(ch[rt][0], ch[rt][1]);
    int ll = ch[rt][0]; int rr = ch[rt][1];
    colorrev[rt] ^= 1;
}

void up(int rt)
{
    int ll = ch[rt][0]; int rr = ch[rt][1];
    Size[rt] = Size[ll] + Size[rr] + 1;
}

void down(int rt)
{
    int ll = ch[rt][0]; int rr = ch[rt][1];
    if (colorrev[rt]) {
        downrev(ll); downrev(rr);
        colorrev[rt] = 0;
    }
    if (coloradd[rt]) {
        downadd(ll, coloradd[rt]); downadd(rr, coloradd[rt]);
        coloradd[rt] = 0;
    }
}

void Treaval(int x) {
    if (x) {
        down(x);
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x]);
        Treaval(ch[x][1]);
    }
}
void debug() { //printf("%d\n", root);
    Treaval(root);
}

void build(int &x, int l, int r, int fa)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, a[mid]);
    build(ch[x][0], l, mid - 1, x);
    build(ch[x][1], mid + 1, r, x);
    up(x);
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    return r;
}

void rotateto(int x, int goal)
{
    int t = getpos(x);
    splay(t, goal);
}

void gaoadd(int L, int R, int add)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    downadd(keytree, add);
}

void gaoreverse(int L, int R)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    downrev(keytree);
}

void gaoinsert(int x)
{
    rotateto(pos, 0); rotateto(pos + 1, root);
    newnode(keytree, ch[root][1], x);
}
void gaodelete() {
    rotateto(pos - 1, 0); rotateto(pos + 1, root);
    keytree = 0;
}

void ask()
{
    rotateto(pos - 1, 0); rotateto(pos + 1, root);
    printf_(val[keytree]);
    putchar(‘\n‘);
}

void init()
{
    root = tot = 0;
    ch[0][1] = ch[0][0] = Size[0] = val[0] = coloradd[0] = colorrev[0] = pre[0] = 0;
    newnode(root, 0, -1);
    newnode(ch[root][1], root, -1);
    build(keytree, 0, n - 1, ch[root][1]);
}

void gaoreverse1(int L, int R, int L1, int R1)//跨越两端的区间翻转,先将两边的翻转,然后交换位置
{
    rotateto(L - 1, 0); rotateto(R + 1, root);
    int t = keytree; int t1 = ch[root][1]; int t2 = root;
    downrev(keytree);
    keytree = 0;
    rotateto(L1 - 1, 0); rotateto(R1 + 1, root);
    int t3 = keytree; downrev(keytree);
    keytree = t;
    pre[t] = ch[root][1];
    splay(t2, 0); splay(t1, root);
    keytree = t3;
    pre[t3] = ch[root][1];
    splay(keytree, 0);
}

int main()
{
    int k1, k2, m, x;
    char str[10];
    int Icase = 0;
    while (scanf_(n)) {
        scanf_(m); scanf_(k1); scanf_(k2);
        if (n == 0 && m == 0 && k1 == 0 && k2 == 0) break;
        printf("Case #%d:\n", ++Icase);
        for (int i = 0; i < n; i++) {
            scanf_(a[i]);
        }
        init();
        pos = 1;
        while (m--) {
            scanf("%s", str);
            if (str[0] == ‘a‘) {
                scanf_(x);
                int t = pos + k2 - 1;
                if (t <= n) {
                    gaoadd(pos, t, x);
                }
                else {
                    gaoadd(pos, n, x);
                    t %= n;
                    gaoadd(1, t, x);
                }
            }
            if (str[0] == ‘r‘) {
                int t = pos + k1 - 1;
                if (t <= n) {
                    gaoreverse(pos, t);
                }
                else {
                    gaoreverse1(pos, n, 1, t%n);
                    pos = (n + 1) - (t%n); // 结点翻转交换以后,pos的位置更新
                }
            }
            if (str[0] == ‘i‘) {
                scanf_(x);
                gaoinsert(x); n++;
            }
            if (str[0] == ‘d‘) {
                gaodelete();
                n--;
                if (pos > n) pos = 1;
            }
            if (str[0] == ‘m‘) {
                scanf_(x);
                if (x == 1) {
                    pos--;
                    if (pos == 0) pos = n;
                }
                if (x == 2) {
                    pos++;
                    if (pos == n + 1) pos = 1;
                }
            }
            if (str[0] == ‘q‘) {
                ask();
            }
        }

    }
    return 0;
}

HDU4441Queue Sequence 12年天津

有个插入操作,在它插入的位置后面离他最近的正数所对应的负数前面插入它的负数。

怎么搞呢?别人教我的,每个节点再维护一个价值,如果这个结点是负数则这个结点的价值是1,然后在维护区间和,这样就可以通过左子树的区间和大小,从根向下查到离他最近的价值为1的位置。

还有一个要注意的小点,由于每个正数只出现一次,在建立结点的时候就可以记录这个数字所对应的结点,然后注意点细节,调就好了。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]
const int maxn = 4e5 + 20;
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
const int INF = 1e9;
int sum1[maxn << 2];
void build(int l, int r, int rt)
{
    sum1[rt] = 0;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(lson); build(rson);
}
void up1(int rt)
{
    sum1[rt] = sum1[rt << 1] + sum1[rt << 1 | 1];
}
void update(int key, int l, int r, int rt)
{
    if (l == r) {
        sum1[rt] ^= 1; return;
    }
    int mid = (l + r) >> 1;
    if (key <= mid) update(key, lson);
    else update(key, rson);
    up1(rt);
}
int ask(int l, int r, int rt)
{
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int len = mid - l + 1;
    if (sum1[rt << 1] == len) return ask(rson);
    else return ask(lson);
}
int tot, root, pre[maxn], ch[maxn][2], Size[maxn], pos[maxn], LL[maxn], val[maxn], oppo[maxn], n;
int suml[maxn];
long long  sum[maxn];
void Treaval(int x) {
    if (x) {
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d suml = %d\n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x],suml[x]);
        Treaval(ch[x][1]);
    }
}
void debug() { printf("%d\n", root); Treaval(root); }

void newnode(int &x, int fa, int key)
{
    x = ++tot;
    pre[x] = fa;
    Size[x] = 1; ch[x][0] = ch[x][1] = 0;
    val[x] = key;
    sum[x] = key;
    if (key > 0) pos[key] = x;
    if (key > 0) LL[x] = 1, suml[x] = 1;
    else LL[x] = 0, suml[x] = 0;
}
void up(int x)
{
    int ll = ch[x][0]; int rr = ch[x][1];
    Size[x] = Size[ll] + Size[rr] + 1;
    sum[x] = sum[ll] + sum[rr] + val[x];
    suml[x] = suml[ll] + suml[rr] + LL[x];
}
void rotate(int x, int kind)
{
    int y = pre[x];
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}

inline void splay(int x, int goal)
{
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            //down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int r = root;
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
    }
    return r;
}

void rotateto(int x, int goal)
{
    int t = getpos(x);
    splay(t, goal);
}
int getpre(int i) {
    splay(i, 0);
    int r = root;
    r = ch[root][0];

    while (ch[r][1]) {
        r = ch[r][1];
    }
    return r;
}
int getlast(int i) {
    splay(i, 0);
    int r = root;
    r = ch[root][1];
    while (ch[r][0])
        r = ch[r][0];
    return r;
}

int asklast(int r)
{
    //printf("%d %d %d asdf\n",r,ch[r][1], suml[ch[r][1]]);
    int ll = ch[r][0];
    int rr = ch[r][1];
    if (ch[r][1] == 0) return -1;
    if (suml[rr] == 0) return -1;
    r = ch[r][1];
    while (r) {
        ll = ch[r][0]; rr = ch[r][1];
        if (suml[ll] == 0 && LL[r]) break;
        if (suml[ll]) r = ch[r][0];
        else r = ch[r][1];
    }
    return r;
}

void insert(int p)
{
    int t = ask(1, n, 1);
    rotateto(p, 0); rotateto(p + 1, root);
    newnode(keytree, ch[root][1], t);
    splay(keytree, 0);
    update(t, 1, n, 1);
    int t1 = asklast(root);
    if (t1 == -1) {
        int ll = getpre(2);
        splay(ll, 0); splay(2, root);
        newnode(keytree, ch[root][1], -t);
        oppo[t] = keytree;
    }
    else {
        int ll = getpre(oppo[val[t1]]);
        splay(ll, 0); splay(oppo[val[t1]], root);
        newnode(keytree, ch[root][1], -t);
        oppo[t] = keytree;
    }
}

void remove(int i)
{
    int ll = getpre(pos[i]); int rr = getlast(pos[i]);
    splay(ll, 0); splay(rr, root);
    ch[ch[root][1]][0] = 0;
    ll = getpre(oppo[i]); rr = getlast(oppo[i]);
    splay(ll, 0); splay(rr, root);
    ch[ch[root][1]][0] = 0;
    update(i, 1, n, 1);
}
void ask(int i)
{
    int ll = pos[i]; int rr = oppo[i];
    //debug();
    ll = getpre(ll); rr = getlast(rr);
    splay(ll, 0); splay(rr, root);
    printf("%I64d\n", sum[keytree]);
}

void init()
{
    build(1, n, 1);
    root = tot = Size[0] = pos[0] = oppo[0] = suml[0] = LL[0] = 0;
    sum[0] = 0;
    newnode(root, 0, 0);
    newnode(ch[root][1], root, 0);

}

int main()
{
    int a;
    char str[10];
    int Icase = 0;
    while (scanf("%d", &n) != EOF) {
        printf("Case #%d:\n", ++Icase);
        init();
        for (int i = 0; i < n; i++) {
            scanf("%s%d", str, &a);
            if (str[0] == ‘i‘) insert(a);
            if (str[0] == ‘r‘) remove(a);
            if (str[0] == ‘q‘) ask(a);
            //debug();
        }
    }
    return 0;
}

POJ3580SuperMemo

有个特殊的操作,右移,和上题差不多,分成两段,然后重新相连

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]
const int INF = 1e9;
const int maxn = 1e6 + 10;
int root, tot, top2;
int pre[maxn], colorrev[maxn], coloradd[maxn], Size[maxn], Min[maxn], val[maxn];
int ss[maxn], que[maxn];
int ch[maxn][2], a1[maxn];

void newnode(int &x, int fa, int key)
{
    //x = ++tot;
    if (top2) x = ss[--top2];
    else x = ++tot;
    pre[x] = fa;
    ch[x][0] = ch[x][1] = 0;
    val[x] = key; Min[x] = key;
    colorrev[x] = 0; coloradd[x] = 0;
    Size[x] = 1; // 不初始化的话,若每次插入用splay翻上去也是对的,更新的时候Size[x] = Size[0]+1
}

void downrev(int r)
{
    if (r == 0)return;
    swap(ch[r][0], ch[r][1]);
    colorrev[r] ^= 1;
}

void downadd(int r, int v)
{
    if (r == 0) return;
    Min[r] += v;
    val[r] += v;
    coloradd[r] += v;
}

void down(int rt)
{
    if (colorrev[rt]) {
        downrev(ch[rt][0]); downrev(ch[rt][1]);
        colorrev[rt] = 0;
    }
    if (coloradd[rt]) {
        downadd(ch[rt][0], coloradd[rt]);
        downadd(ch[rt][1], coloradd[rt]);
        coloradd[rt] = 0;
    }
}

void up(int rt)
{
    int ll = ch[rt][0]; int rr = ch[rt][1];
    Min[rt] = min(val[rt], min(Min[ll], Min[rr]));
    Size[rt] = Size[ll] + Size[rr] + 1;
}
void Treaval(int x) {
    if (x) {
        down(x);
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d Min=%2d \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x], Min[x]);
        Treaval(ch[x][1]);
    }
}
void debug() { printf("%d\n", root); Treaval(root); }

inline void erase(int x) {//把以x为祖先结点删掉放进内存池,回收内存
    int father = pre[x];
    int head = 0, tail = 0;
    for (que[tail++] = x; head < tail; head++) {
        ss[top2++] = que[head];
        if (ch[que[head]][0]) que[tail++] = ch[que[head]][0];
        if (ch[que[head]][1]) que[tail++] = ch[que[head]][1];
    }
    ch[father][ch[father][1] == x] = 0;
    up(father);
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            //down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    return r;
}

void build(int &x, int l, int r, int fa)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, a1[mid]);
    build(ch[x][0], l, mid - 1, x);
    build(ch[x][1], mid + 1, r, x);
    up(x);
}
void rotateto(int x, int goal)
{
    int pos = getpos(x);
    splay(pos, goal);  //傻逼了 pos 写成x
}

void add(int L, int R, int c)
{
    L--; R++;
    rotateto(L, 0); rotateto(R, root);
    downadd(keytree, c);
}

void revolve(int L, int R, int T)
{
    int ll = L, rr = R;
    L--; R = R - T; R++;
    rotateto(L, 0); rotateto(R, root);
    int t = keytree;
    ch[ch[root][1]][0] = 0;
    int len = rr - T - ll + 1;
    rr -= len;
    rotateto(rr, 0); rotateto(rr + 1, root);
    ch[ch[root][1]][0] = t;
    pre[t] = ch[root][1];
}

void reverse(int L, int R)
{
    L--; R++;
    rotateto(L, 0);
    rotateto(R, root);
    downrev(keytree);
}

void insert(int x, int p)
{
    rotateto(x, 0);
    rotateto(x + 1, root);
    newnode(ch[ch[root][1]][0], ch[root][1], p); //傻逼了  ch[root][1] ->root;
}

void Delete(int x)
{
    int L = x - 1; int R = x + 1;
    rotateto(L, 0); rotateto(R, root);
    erase(ch[ch[root][1]][0]);
}

void askmin(int L, int R)
{
    L--; R++;
    rotateto(L, 0); rotateto(R, root);
    printf("%d\n", Min[keytree]);
}

void init(int n)
{
    Size[0] = colorrev[0] = coloradd[0] = val[0] = ch[0][0] = ch[0][1] = val[0] = 0;
    Min[0] = INF;
    tot = top2 = root = 0;
    newnode(root, 0, -1);
    newnode(ch[root][1], root, -1);
    build(keytree, 0, n - 1, ch[root][1]);
}

int main()
{
    int n;
    int a, b, c, m;
    char str[10];
    while (scanf("%d", &n) != EOF) {
        for (int i = 0; i < n; i++) scanf("%d", &a1[i]);
        init(n);
        scanf("%d", &m);
        while (m--) {
            scanf("%s", str);
            if (str[0] == ‘A‘) {
                scanf("%d%d%d", &a, &b, &c); add(a, b, c);
            }
            if (str[0] == ‘R‘&&str[3] == ‘E‘) {
                scanf("%d%d", &a, &b);
                reverse(a, b); //debug();
                continue;
            }
            if (str[0] == ‘R‘) {
                scanf("%d%d%d", &a, &b, &c);
                c %= (b - a + 1);
                revolve(a, b, c);
            }
            if (str[0] == ‘I‘) {
                scanf("%d%d", &a, &b);
                insert(a, b);
            }
            if (str[0] == ‘D‘) {
                scanf("%d", &a);
                Delete(a);
            }
            if (str[0] == ‘M‘) {
                scanf("%d%d", &a, &b);
                askmin(a, b);
            }
            //debug();
        }
    }
    return 0;
}

文本编辑器editor

没有维修数列复杂,多写写,练手

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]
const int maxn = 2*1024 * 1024 + 20;
int ch[maxn][2], Size[maxn];
int color[maxn], pre[maxn];
char val[maxn];
int tot, root;
int pos;
void Treaval(int x) {
    if (x) {
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %c \n", x, ch[x][0], ch[x][1], pre[x], Size[x], val[x]);
        Treaval(ch[x][1]);
    }
}
void debug() { printf("%d\n", root); Treaval(root); }
void up(int x)
{
    int ll = ch[x][0]; int rr = ch[x][1];
    Size[x] = Size[ll] + Size[rr] + 1;
}

void down(int x)
{
    if (color[x]) {
        swap(ch[x][0], ch[x][1]);
        color[ch[x][0]] ^= 1; color[ch[x][1]] ^= 1;
        color[x] = 0;
    }
}
void newnode(int &r, int fa, char key)
{
    r = ++tot;
    pre[r] = fa;
    ch[r][0] = ch[r][1] = 0;
    val[r] = key;
    Size[r] = 1;
    color[r] = 0;
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    return r;
}

void rotateto(int x, int goal)
{
    int t = getpos(x);
    splay(t, goal);
}

void Delete(int n)
{
    int ll = pos + 1; int rr = pos + n;
    //debug();
    //printf("%d %djiji\n", rr,getpos(rr+1)); system("pause");
    rotateto(ll - 1, 0);
    rotateto(rr + 1, root);
    //debug(); system("pause");
    ch[ch[root][1]][0] = 0;
    //up(ch[root][1]);
    //up(root);
}

void rev(int n)
{
    int ll = pos + 1; int rr = pos + n;
    rotateto(ll - 1, 0); rotateto(rr + 1, root);
    color[keytree] ^= 1;
}

void prev() { pos--; }
void next() { pos++; }
void move(int k) {
    pos = k;
}

int getrt()
{
    int r = root;
    down(r);
    r = ch[r][1];
    down(r);
    while (ch[r][0]) {
        r = ch[r][0];
        down(r);
    }
    return r;
}

void build(int &x, int l, int r, int fa, char str[])
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, str[mid]);
    build(ch[x][0], l, mid - 1, x, str);
    build(ch[x][1], mid + 1, r, x, str);
    up(x);
}

void insert(int n, char str[])
{
    rotateto(pos, 0);
    int rt = getrt();
    build(ch[rt][0], 0, n - 1, rt, str);
    splay(ch[rt][0], 0);
}

void init()
{
    tot = root = 0; Size[0] = color[0] = ch[0][0] = ch[0][1] = 0;
    pre[0] = 0;
    newnode(root, 0, ‘a‘);
    newnode(ch[root][1], root, ‘a‘);
}

void gao()
{
    int t = pos + 1;
    int cc = getpos(t);
    printf("%c\n", val[cc]);
}
char s[maxn];
int main()
{
    int T, n;
    char str[20], gg;
    while (scanf("%d", &T) != EOF) {
        init();
        while (T--) {
            scanf("%s", str);
            if (str[0] == ‘M‘) {
                scanf("%d", &n); move(n);
            }
            if (str[0] == ‘I‘) {
                scanf("%d%c", &n, &gg);
                gets(s);
                insert(n, s);
            }
            if (str[0] == ‘D‘) {
                scanf("%d", &n);
                Delete(n);
            }
            if (str[0] == ‘R‘) {
                scanf("%d", &n);
                rev(n);
            }
            if (str[0] == ‘G‘) {
                gao();
            }
            if (str[0] == ‘P‘) {
                prev();
            }
            if (str[0] == ‘N‘) {
                next();
            }
        }
    }
    return 0;
}

HDU3487Play with Chain

有个cut操作,也是先删除,然后插入。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]
const int maxn = 3e5 + 20;
int tot, root;
int ch[maxn][2], pre[maxn], color[maxn], Size[maxn], val[maxn];
int n;

void Treaval(int x) {
    if (x) {
        Treaval(ch[x][0]);
        printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %d val = %d \n", x, ch[x][0], ch[x][1], pre[x], Size[x],val[x]);
        Treaval(ch[x][1]);
    }
}
void debug() { printf("%d\n", root); Treaval(root); }
void newnode(int &r, int fa, int key)
{
    r = ++tot;
    pre[r] = fa;
    ch[r][0] = ch[r][1] = 0;
    color[r] = 0;
    val[r] = key;
    Size[r] = 1;
}

void down(int x)
{
    if (color[x]) {
        swap(ch[x][0], ch[x][1]);
        int ll = ch[x][0]; int rr = ch[x][1];
        color[ll] ^= 1; color[rr] ^= 1;
        color[x] = 0;
    }
}

void up(int x)
{
    int ll = ch[x][0]; int rr = ch[x][1];
    Size[x] = Size[ll] + Size[rr] + 1;
}

int getpos(int k)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) r = ch[r][0];
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    return r;
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

void rotateto(int x, int goal)
{
    int t = getpos(x);
    splay(t, goal);
}

void build(int &x, int l, int r, int fa)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, mid);
    build(ch[x][0], l, mid - 1,x);
    build(ch[x][1], mid + 1, r,x);
    up(x);
}

void init()
{
    root = tot = 0;
    Size[0] = 0; color[0] = 0; val[0] = 0; ch[0][1] = ch[0][0] = 0;
    newnode(root, 0, -1);
    newnode(ch[root][1], root, -1);
    build(keytree, 1, n, ch[root][1]);
}

void flip(int L, int R)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    color[keytree] ^= 1;
    //splay(keytree, 0);
}

void insert(int rt)
{
    int r = root;
    down(r);
    if (ch[r][1]) r = ch[r][1];
    down(r);
    while (ch[r][0]) {
        r = ch[r][0]; down(r);
    }
    ch[r][0] = rt; pre[rt] = r;
    up(r);
}

void cut(int L, int R, int pos)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    int cc = keytree;
    ch[ch[root][1]][0] = 0;
    rotateto(pos, 0);
    insert(cc);
    splay(cc, 0); // 这里要翻上去
}
int ans[maxn];
int cnt = 0;

void show(int root)
{
    if (root) {
        down(root);
        show(ch[root][0]);
        if (root != 1 && root != 2) ans[cnt++] = val[root];
        show(ch[root][1]);
    }
}

int main()
{
    int m;
    char str[10];
    int a, b, c;
    while (scanf("%d%d", &n, &m) != EOF) {
        cnt = 0;
        if (n == -1 && m == -1)  break;
        init();
        while (m--) {
            scanf("%s", str);
            if (str[0] == ‘C‘) {
                scanf("%d%d%d", &a, &b, &c);
                cut(a, b, c);
            }
            else {
                scanf("%d%d", &a, &b);
                flip(a, b);
            }
        }
        show(root);
        for (int i = 0; i < cnt; i++) {
            if (i) printf(" ");
            printf("%d", ans[i]);
        }
        cout << endl;
    }
    return 0;
}

HDU1890Robotic Sort

先排序,然后保存下位置。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#include<stack>
#include<list>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include <fstream>
using namespace std;
#define keytree ch[ ch[root][1]][0]

const int maxn = 1e5 + 20;
int tot, root;
int n;
int pre[maxn], ch[maxn][2], color[maxn], pos[maxn], Size[maxn], a[maxn];
int val[maxn];
void down(int x)
{
    if (color[x]) {
        swap(ch[x][0], ch[x][1]);
        int ll = ch[x][0]; int rr = ch[x][1];
        color[ll] ^= 1; color[rr] ^= 1;
        color[x] = 0;
    }
}
void newnode(int &r, int fa, int key)
{
    r = ++tot;
    pre[r] = fa;
    ch[r][0] = ch[r][1] = 0;
    color[r] = 0;
    Size[r] = 1;
    pos[key] = r;
    val[r] = key;
}

void up(int x)
{
    int ll = ch[x][0]; int rr = ch[x][1];
    Size[x] = Size[ll] + Size[rr] + 1;
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    ch[x][kind] = y;
    pre[x] = pre[y];
    pre[y] = x;
    up(y);
}
inline void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            down(z); down(y); down(x); //先down z  减少 rotateto 里面的  down y ,x 次数
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

int getpos(int k)
{
    int x = root;
    for(;;){
        down(x);
        if(Size[ch[x][0]]==k) break;
        if(k<Size[ch[x][0]]){
            x = ch[x][0] ;
        }
        else{
            k -= Size[ch[x][0]] + 1;
            x = ch[x][1] ;
        }
    }
    return x;
}

void build(int &x, int fa, int l, int r)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, a[mid]);
    build(ch[x][0], x, l, mid - 1);
    build(ch[x][1], x, mid + 1, r);
    up(x);
}

void update(int x)
{
    int t;
    splay(pos[x], 0);
    printf("%d", Size[ch[root][0]] + x - 1);
    int l = 1;
    int r = getpos(Size[ch[root][0]] + 1);
    splay(l, 0);
    splay(r, root);
    color[keytree] ^= 1;
    t = getpos(2);
    splay(1, 0);
    splay(t, root);
    ch[ch[root][1]][0] = 0;
}

void init()
{
    Size[0] = pre[0] = ch[0][1] = ch[0][0] = color[0] = 0;
    tot = root = 0;
    newnode(root, 0, 0);
    newnode(ch[root][1], root, 0);
    build(keytree, ch[root][1], 1, n);
}

struct Node
{
    int val; int id;
}b[maxn];

int cmp(const Node &a, const Node &b)
{
    return a.val != b.val ? a.val < b.val : a.id < b.id;
}
void gao()
{
    for (int i = 1; i <= n; i++) b[i].val = a[i], b[i].id = i;
    sort(b + 1, b + 1 + n, cmp);
    for (int i = 1; i <= n; i++) {
        int t = b[i].id;
        a[t] = i;
    }

}

int main()
{
    while (scanf("%d", &n) && n) {
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        gao();
        init();
        for (int i = 1; i <= n; i++) {
            if (i != 1) printf(" ");
            update(i);
        }
        cout << endl;
    }
    return 0;
}

poj3468A Simple Problem with Integers

求区间和,值得学习的是建树方式。

#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <time.h>
#include <set>
using namespace std;
const int maxn = 1e5 + 20;
int tot, root, n;
int ch[maxn][2], pre[maxn], Size[maxn], aa[maxn];
typedef long long LL;
LL sum[maxn], val[maxn], color[maxn];
void newnode(int &r, int fa, int k)
{
    r = ++tot;
    ch[r][0] = ch[r][1] = 0;
    pre[r] = fa;
    sum[r] = k;
    color[r] = 0;
    Size[r] = 1;
    val[r] = k;
}

void up(int x)
{
    int ll = ch[x][0]; int rr = ch[x][1];
    sum[x] = sum[ll] + sum[rr] + val[x];
    Size[x] = Size[ll] + Size[rr] + 1;
}

void down(int x)
{
    if (color[x]) {
        int ll = ch[x][0]; int rr = ch[x][1];
        color[ll] += color[x]; color[rr] += color[x];
        sum[ll] += Size[ll] * color[x]; sum[rr] += color[x] * Size[rr];
        val[x] += color[x];
        color[x] = 0;
    }
}

void rotate(int x, int kind)
{
    int y = pre[x];
    down(y); down(x);
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    pre[x] = pre[y];
    pre[y] = x;
    ch[x][kind] = y;
    up(y);
}

void splay(int x, int goal)
{
    down(x);
    while (pre[x] != goal) {
        if (pre[pre[x]] == goal) rotate(x, ch[pre[x]][0] == x);
        else {
            int y = pre[x]; int z = pre[y];
            int kind = ch[z][0] == y;
            if (ch[y][kind] == x) {
                rotate(x, !kind);
                rotate(x, kind);
            }
            else {
                rotate(y, kind);
                rotate(x, kind);
            }
        }
    }
    up(x);
    if (goal == 0) root = x;
}

void rotateto(int k, int goal)
{
    int r = root;
    down(r);
    while (Size[ch[r][0]] != k) {
        if (k < Size[ch[r][0]]) {
            r = ch[r][0];
        }
        else {
            k -= Size[ch[r][0]] + 1;
            r = ch[r][1];
        }
        down(r);
    }
    splay(r, goal);
}

void build(int &x, int fa, int l, int r)
{
    if (l > r) return;
    int mid = (l + r) >> 1;
    newnode(x, fa, aa[mid]);
    if (l<mid)
        build(ch[x][0], x, l, mid - 1);
    if (r>mid)
        build(ch[x][1], x, mid + 1, r);
    up(x);
}

void update(int L, int R, int add)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    int x = ch[root][1];
    x = ch[x][0];
    color[x] += add;
    sum[x] += Size[x] * add;
    splay(x, 0);
}

void ask(int L, int R)
{
    rotateto(L - 1, 0);
    rotateto(R + 1, root);
    int x = ch[root][1]; x = ch[x][0];
    printf("%I64d\n", sum[x]);
}

void init()
{
    root = tot = 0;
    ch[0][0] = ch[0][1] = pre[0] = Size[0] = color[0] = sum[0] = 0;
    newnode(root, 0, -1);
    newnode(ch[root][1], root, -1);;
    Size[root] = 2;
    int k = ch[root][1];
    build(ch[k][0], k, 0, n - 1);
    up(k);
    up(root);
}

int main()
{
    int  m, a, b, c;
    char str[10];
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 0; i < n; i++) scanf("%d", &aa[i]);
        init();
        while (m--) {
            scanf("%s", str);
            if (str[0] == ‘C‘) {
                scanf("%d%d%d", &a, &b, &c);
                update(a, b, c);
            }
            else {
                scanf("%d%d", &a, &b);
                ask(a, b);
            }
        }
    }
    return 0;
}

营业额统计

需要求前驱和后继,仔细想想,先找到左子树,然后一直往右走

#define _CRT_SECURE_NO_WARNINGS
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <time.h>
#include <set>
typedef long long LL;

using namespace std;
int tot, root;
const int maxn = 1e6 + 10;
int pre[maxn], ch[maxn][2], key[maxn];

void newnode(int &r, int fa, int k)
{
    r = ++tot;
    pre[r] = fa;
    ch[r][0] = ch[r][1] = 0;
    key[r] = k;
}

void rotate(int x, int kind)
{
    int y = pre[x];
    ch[y][!kind] = ch[x][kind];
    pre[ch[x][kind]] = y;
    if (pre[y]) ch[pre[y]][ch[pre[y]][1] == y] = x;
    pre[x] = pre[y];
    ch[x][kind] = y;
    pre[y] = x;
}

void splay(int r, int goal)
{
    while (pre[r] != goal) {
        if (pre[pre[r]] == goal) rotate(r, ch[pre[r]][0]==r);
        else {
            int y = pre[r];
            int kind = ch[pre[y]][0] == y;
            if (ch[y][kind] == r) {
                rotate(r, !kind);
                rotate(r, kind);
            }
            else {
                rotate(y, kind);
                rotate(r, kind);
            }
        }
    }
    if (goal == 0) root = r;
}

void insert(int k)
{
    int r = root;
    if (root == 0) {
        newnode(root, 0, k);
        return;
    }
    while (ch[r][key[r] < k]) r = ch[r][key[r] < k];
    newnode(ch[r][key[r] < k], r, k);
    splay(ch[r][key[r]<k], 0);
}

int askpre()
{
    int r = root;
    if (ch[r][0]) r = ch[r][0];
    while (ch[r][1]) r = ch[r][1];
    if (r == root) return 1e9;
    return key[r];
}

int asklast()
{
    int r = root;
    if (ch[r][1]) r = ch[r][1];
    while (ch[r][0]) r = ch[r][0];
    if (r == root) return 1e9;
    return key[r];
}

int main()
{
    int a;
    int n;
    int ans = 0;
    scanf("%d", &n);
    root = tot = 0;
    for (int i = 0; i < n; i++) {
        if (scanf("%d", &a) == EOF) a = 0;
        insert(a);
        int Min = 1e9;
        int t = askpre(); int t1 = asklast();
        if (t != 1e9) Min = min(Min, abs(a - t));
        if (t1 != 1e9) Min = min(Min, abs(a - t1));
        if(Min!=1e9)
        ans += Min;
        else ans += a;
    }
    printf("%d\n", ans);
    return 0;
}

时间: 2024-11-03 01:39:03

Splay小结的相关文章

NOIP2017小结

title: NOIP2017小结 tags: --- Day2 T3 题意十分的简洁,就是需要弄个数据结构去维护一个矩阵中,删除一个位置,然后把这一行左移一个单位,再把最后一列前移一个单位.反正,我一看就觉得是线段树,直接建\(n+1\)个线段树,就可以直接搞了,二看就觉得空间分分钟炸掉.于是就没啥办法了. \(30pts\) 考虑\(30pts\)的数据,暴力模拟就好了. \(50pts\) 然后还有一个\(20pts\)的数据,\(q\)比较小,似乎有一种\(q^2\)的做法,反正我是不会

使用Apache POI导出Excel小结--导出XLS格式文档

使用Apache POI导出Excel小结 关于使用Apache POI导出Excel我大概会分三篇文章去写 使用Apache POI导出Excel小结--导出XLS格式文档 使用Apache POI导出Excel小结--导出XLSX格式文档 使用Apache POI导出Excel--大数量导出 导出XLS格式文档 做企业应用项目难免会有数据导出到Excel的需求,最近在使用其,并对导出Excel封装成工具类开放出来供大家参考.关于Apache POI Excel基本的概念与操作我在这里就不啰嗦

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

[题目分析] 模板题目. 首尾两个虚拟结点,十分方便操作. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include

及其简短的Splay代码

#include <stdio.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <math.h> #include <iostream> #define inf 1000000000 using namespace std; #define getch() getchar() inline int F() {register int aa ,

【转载】小结一下linux 2.6内核的四种IO调度算法

在LINUX 2.6中,有四种关于IO的调度算法,下面综合小结一下: 1) NOOP NOOP算法的全写为No Operation.该算法实现了最最简单的FIFO队列,所有IO请求大致按照先来后到的顺序进行操作.之所以说“大致”,原因是NOOP在FIFO的基础上还做了相邻IO请求的合并,并不是完完全全按照先进先出的规则满足IO请求.NOOP假定I/O请求由驱动程序或者设备做了优化或者重排了顺序(就像一个智能控制器完成的工作那样).在有些SAN环境下,这个选择可能是最好选择.Noop 对于 IO

BZOJ_1014_[JSOI2008]_火星人prefix_(Splay+LCP_Hash+二分)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1014 给出一个字符串,有修改,插入,以及询问LCP(i,j)的操作. 分析 LCP在白书上面有介绍,\(LCP(i,j)\)表示以第\(i\)位和以第\(j\)位开头的后缀的最长公共前缀. 先考虑没有插入和修改操作的问题.我们可以用基于Hash的LCP算法. 我们给每一个后缀一个Hash值.其中以第\(i\)为开头的后缀的Hash值为\(H[i]=H[i+1]x+s[i]\). 其中\(x\

BZOJ 1251 序列终结者(Splay)

题目大意 网上有许多题,就是给定一个序列,要你支持几种操作:A.B.C.D.一看另一道题,又是一个序列要支持几种操作:D.C.B.A.尤其是我们这里的某人,出模拟试题,居然还出了一道这样的,真是没技术含量……这样 我也出一道题,我出这一道的目的是为了让大家以后做这种题目有一个“库”可以依靠,没有什么其他的意思.这道题目 就叫序列终结者吧.[问题描述] 给定一个长度为N的序列,每个序列的元素是一个整数(废话).要支持以下三种操作: 1. 将 [L, R] 这个区间内的所有数加上 V. 2. 将 [

Android基础入门教程——8.1.3 Android中的13种Drawable小结 Part 3

Android基础入门教程--8.1.3 Android中的13种Drawable小结 Part 3 标签(空格分隔): Android基础入门教程 本节引言: 本节我们来把剩下的四种Drawable也学完,他们分别是: LayerDrawable,TransitionDrawable,LevelListDrawable和StateListDrawable, 依旧贴下13种Drawable的导图: 1.LayerDrawable 层图形对象,包含一个Drawable数组,然后按照数组对应的顺序来

Android基础入门教程——8.1.2 Android中的13种Drawable小结 Part 2

Android基础入门教程--8.1.2 Android中的13种Drawable小结 Part 2 标签(空格分隔): Android基础入门教程 本节引言: 本节我们继续来学习Android中的Drawable资源,上一节我们学习了: ColorDrawable:NinePatchDrawable: ShapeDrawable:GradientDrawable!这四个Drawable~ 而本节我们继续来学习接下来的五个Drawable,他们分别是: BitmapDrawable:Insert