首页 > 代码库 > 及其简短的Splay代码

及其简短的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 , bb , ch;
    while(ch = getch() , (ch<0||ch>9) && ch != -); ch == - ? aa=bb=0 : (aa=ch-0,bb=1);
    while(ch = getch() , ch>=0&&ch<=9) aa = aa*10 + ch-0; return bb ? aa : -aa;
}
const int Maxn = 1000005;
queue<int> q;
int n , m , root , sz;
int fa[Maxn] , c[Maxn][2] , mx[Maxn] , lx[Maxn] , rx[Maxn] , v[Maxn] , size[Maxn] , sum[Maxn] , a[Maxn] , id[Maxn];
bool lazy[Maxn] , rev[Maxn];
 
void update(int x) {
    int lc = c[x][0] , rc = c[x][1];
    sum[x] = sum[lc] + sum[rc] + v[x];
    size[x] = size[lc] + size[rc] + 1;
    mx[x] = max(mx[lc] , mx[rc]);
    mx[x] = max(mx[x] , rx[lc]+v[x]+lx[rc]);
    lx[x] = max(lx[lc] , sum[lc] + v[x] + lx[rc]);
    rx[x] = max(rx[rc] , sum[rc] + v[x] + rx[lc]);
}
 
void downpush(int x) {
    int lc = c[x][0] , rc = c[x][1];
    if(lazy[x]) {
        rev[x] = lazy[x] = 0;
        if(lc) lazy[lc] = 1 , v[lc] = v[x] , sum[lc] = v[x]*size[lc];
        if(rc) lazy[rc] = 1 , v[rc] = v[x] , sum[rc] = v[x]*size[rc];
        if(v[x] >= 0) {
            if(lc) lx[lc] = rx[lc] = mx[lc] = sum[lc];
            if(rc) lx[rc] = rx[rc] = mx[rc] = sum[rc];
        }
        else {
            if(lc) lx[lc] = rx[lc] = 0 , mx[lc] = v[x];
            if(rc) lx[rc] = rx[rc] = 0 , mx[rc] = v[x];
        }
    }
    if(rev[x]) {
        rev[x] = 0;
        rev[lc] ^= 1;
        rev[rc] ^= 1;
        swap(lx[lc] , rx[lc]);
        swap(lx[rc] , rx[rc]);
        c[x][0] = rc;
        c[x][1] = lc;
        swap(lx[x] , rx[x]);
    }
}
 
void rotate(int&root , int x) {
    int y = fa[x] , z = fa[y] , p , q;
    if(x == c[y][0]) p = 0; else p = 1;
    q = p^1;
    if(y == root) root = x;
    else {
        if(c[z][0] == y) c[z][0] = x;
        else c[z][1] = x;
    }
    fa[x] = z; fa[y] = x; fa[c[x][q]] = y;
    c[y][p] = c[x][q]; c[x][q] = y;
    update(y); update(x);
}
void splay(int&root , int x) {
    int y , z;
    while(x != root) {
        y = fa[x] , z = fa[y];
        if(y != root) {
            if((x == c[y][0]) ^ (y == c[z][0])) rotate(root , x);
            else rotate(root , y);
        }
        rotate(root , x);
    }
}
 
int find(int x , int rk) {
    downpush(x);
    int lc = c[x][0] , rc = c[x][1];
    if(size[lc] + 1 == rk) return x;
    if(size[lc] >= rk) return find(lc , rk);
    else return find(rc , rk-size[lc]-1);
}
 
void rec(int x) {
    if(!x) return ;
    int lc = c[x][0] , rc = c[x][1];
    rec(lc);rec(rc);q.push(x);
    fa[x] = c[x][0] = c[x][1] = lazy[x] = rev[x] = 0;
}
 
int split(int k , int tot) {
    int x = find(root , k);
    splay(root , x);
    x = find(root , k+tot+1);
    splay(c[root][1] , x);
    return c[ c[root][1] ][0];
}
 
void query(int k , int tot) {
    int x = split(k , tot);
    printf("%d\n",sum[x]);
}
 
void modify(int k , int tot , int val) {
    int x = split(k , tot) , y = fa[x];
    v[x] = val; lazy[x] = 1; sum[x] = size[x]*val;
    if(val >= 0) lx[x] = rx[x] = mx[x] = sum[x];
    else lx[x] = rx[x] = 0 , mx[x] = val;
    update(y); update(fa[y]);
}
 
void reverse(int k , int tot) {
    int x = split(k , tot);
    if(!lazy[x]) {
        rev[x] ^= 1;
        downpush(x);
        update(fa[x]);
        update(fa[fa[x]]);
    }
}
 
void erase(int k , int tot) {
    int x = split(k , tot) , y = fa[x];
    rec(x); c[y][0] = 0;
    update(y); update(fa[y]);
}
void build(int l,int r,int f)
{
    if(l>r)return;
    int mid=(l+r)>>1,now=id[mid],last=id[f];
    if(l==r)
    {
        sum[now]=a[l];size[now]=1;
        lazy[now]=rev[now]=0;
        if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[l];
        else lx[now]=rx[now]=0,mx[now]=a[l];
    }
    else build(l,mid-1,mid),build(mid+1,r,mid);
    v[now]=a[mid];fa[now]=last;update(now);
    c[last][mid>=f]=now;
   }
void insert(int k,int tot)
{
    for(int i=1;i<=tot;i++)a[i]=F();
    for(int i=1;i<=tot;i++)
        if(!q.empty())id[i]=q.front(),q.pop();
        else id[i]=++sz;
    build(1,tot,0);int z=id[(1+tot)>>1];
    int x=find(root,k+1),y=find(root,k+2);
    splay(root,x);splay(c[x][1],y);
    fa[z]=y;c[y][0]=z;
    update(y);update(x);
}
 
int main() {
    n = F(); m = F();
    mx[0] = a[1] = a[n+2] = -inf;
    for(int i=1; i<=n; ++i) {
        a[i+1] = F();
    }
    for(int i=1;i<=n+2;i++)id[i]=i;
    build(1,n+2,0);
    root = (n+3) >> 1;sz = n + 2;
    int k , tot , val;
    char ch[10];
    while(m--) {
        scanf("%s",ch);
        if(ch[0]!=M || ch[2] != X) k = F() , tot = F();
        if(ch[0] == I) insert(k , tot);
        if(ch[0] == D) erase(k , tot);
        if(ch[0] == M) {
            if(ch[2] == X) printf("%d\n",mx[root]);
            else val = F() , modify(k , tot , val);
        }
        if(ch[0] == R) reverse(k , tot);
        if(ch[0] == G) query(k , tot);
    }
}

Splay的核心操作

void rotate(int&root , int x) {
    int y = fa[x] , z = fa[y] , p , q;
    if(x == c[y][0]) p = 0; else p = 1;
    q = p^1;
    if(y == root) root = x;
    else {
        if(c[z][0] == y) c[z][0] = x;
        else c[z][1] = x;
    }
    fa[x] = z; fa[y] = x; fa[c[x][q]] = y;
    c[y][p] = c[x][q]; c[x][q] = y;
    update(y); update(x);
}
void splay(int&root , int x) {
    int y , z;
    while(x != root) {
        y = fa[x] , z = fa[y];
        if(y != root) {
            if((x == c[y][0]) ^ (y == c[z][0])) rotate(root , x);
            else rotate(root , y);
        }
        rotate(root , x);
    }
}

 

及其简短的Splay代码