伸展树模板(BZOJ 1500,UVALive 3961 HDU 1890)

伸展树和名次树基本上差不多,直接上模板。

HYSBZ 1500维修数列

链表实现

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-6
#define CLR( a, v ) memset ( a, v, sizeof ( a ) )
#define LL long long
#define DBUG printf ( "here!!!\n" )
#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )
#define PB push_back
#define ULL unsigned long long
#define PI acos ( -1.0 )
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define lowbit( x ) ( ( x )&( -x ) )
#define CASE int Test; scanf ( "%d", &Test ); for ( int cas = 1; cas <= Test; cas ++ )
#define ALL( x ) x.begin ( ), x.end ( )
#define INS( x ) x, x.begin ( )
typedef pair < int, int > Pii;
typedef pair < double, double > Pdd;
typedef set < int > Set;
const int maxn = 500005;
int read_int ( )
{
    int res = 0;
    int ch;
    while ( ( ch = getchar ( ) ) && ! ( ch >= '0' && ch <= '9' ) )
    {
        if ( ch == -1 )
            return -1;
    }
    while ( ch >= '0' && ch <= '9' )
    {
        res = res*10+( ch-'0' );
        ch = getchar ( );
    }
    return res;
}
struct Node
{
    int x, cnt, lv, mv, rv, rev;
    int md, sum;
    struct Node * ch[2];
    void maintain ( )
    {
        cnt = ch[0]->cnt+ch[1]->cnt+1;
        sum = ch[0]->sum+ch[1]->sum+x;
        //维护子串和
        lv = max ( ch[0]->lv, ch[0]->sum+x+max ( 0, ch[1]->lv ) );
        rv = max ( ch[1]->rv, ch[1]->sum+x+max ( 0, ch[0]->rv ) );
        mv = max ( ch[0]->mv, ch[1]->mv );
        mv = max ( mv, max ( 0, ch[0]->rv )+x+max ( 0, ch[1]->lv )  );
    }
    void modify ( int s )
    {
        md = s;
        x = s;
        lv = mv = rv = max ( s, cnt*s );    //s可能为负数
        sum = cnt*s;
    }
    void reverse ( )
    {
        swap ( ch[0], ch[1] );
        swap ( lv, rv );
        rev ^= 1;   //注意只要当前rev更新
    }
    void PushDown ( )
    {
        if ( md != INF )
        {
            rev = 0;
            if ( ch[0]->cnt )
                ch[0]->modify ( md );
            if ( ch[1]->cnt )
                ch[1]->modify ( md );
            md = INF;
        }
        if ( rev )
        {
            rev = 0;
            if ( ch[0]->cnt )
                ch[0]->reverse ( );
            if ( ch[1]->cnt )
                ch[1]->reverse ( );
        }
    }
    int cmp ( int k )
    {
        int d = k-ch[0]->cnt;
        if ( d == 1 )
            return -1;
        return d <= 0 ? 0 : 1;
    }
}*root, *null;
int a[maxn], cc;
Node * Build ( int L, int R )
{
    if ( L >= R )
        return null;
    int M = ( L+R ) >> 1;
    Node * p = new Node ( );
    p->x = p->lv = p->mv = p->rv = p->sum = a[M];
    p->rev = 0;
    p->md = INF;
    p->ch[0] = Build ( L, M );
    p->ch[1] = Build ( M+1, R );
    p->maintain ( );
    return p;
}
void Rotate ( Node * &o, int k )
{
    Node * p = o->ch[k^1];
    o->ch[k^1] = p->ch[k];
    p->ch[k] = o;
    o->maintain ( );
    p->maintain ( );
    o = p;
}
void splay ( Node * &o, int k )
{
    o->PushDown ( );
    int d = o->cmp ( k );
    if ( d == 1 )
        k -= o->ch[0]->cnt+1;
    if ( d != -1 )
    {
        Node * p = o->ch[d];
        p->PushDown ( );
        int d2 = p->cmp ( k );
        int k2 = ( d2 == 0 ? k : k-p->ch[0]->cnt-1 );
        if ( d2 != -1 )
        {
            splay ( p->ch[d2], k2 );
            if ( d == d2 )
                Rotate ( o, d^1 );
            else
                Rotate ( o->ch[d], d );
        }
        Rotate ( o, d^1 );
    }
    o->maintain ( );
}
void split ( Node * o, int k, Node * &left, Node * &right )
{
    splay ( o, k );
    left = o;
    right = o->ch[1];
    left->ch[1] = null;
    left->maintain ( );
}
Node * Merge ( Node * left, Node * right )
{
    splay ( left, left->cnt );
    left->ch[1] = right;
    left->maintain ( );
    return left;
}
void print ( Node * o )
{
    if ( o == null )
        return ;
    o->PushDown ( );
    print ( o->ch[0] );
    printf ( "%d ", o->x );
    print ( o->ch[1] );
}
void remove ( Node * &o )
{
    if ( o == null )
        return ;
    remove ( o->ch[0] );
    remove ( o->ch[1] );
    delete o;
    o = null;
}
void solve ( )
{
    int n, m, pos, tot, x;
    char op[15];
    null = new Node ( );
    null->x = null->cnt = null->rev = null->sum = 0;
    null->lv = null->mv = null->rv = -INF;
    Node *o, *left, *mid, *right;

    //freopen ( "in0.in", "r", stdin );
    //freopen ( "in1.out", "w", stdout );
    scanf ( "%d%d", &n, &m );
    cc = 0;
    for ( int i = 1; i <= n; i ++ )
        scanf ( "%d", &a[i] );
    root = Build ( 1, n+1 );
    while ( m -- )
    {
        scanf ( "%s", op );
        if ( op[0] == 'I' )
        {
            scanf ( "%d%d", &pos, &tot );
            if ( tot == 0 )
                continue ;
            for ( int i = 1; i <= tot; i ++ )
                scanf ( "%d", &a[i] );
            o = Build ( 1, tot+1 );
            if ( pos == 0 )
                root = Merge ( o, root );
            else
            {
                split ( root, pos, left, right );
                root = Merge ( Merge ( left, o ), right );
            }
        }
        else if ( op[0] == 'D' )
        {
            scanf ( "%d%d", &pos, &tot );
            if ( tot == 0 )
                continue ;
            if ( pos == 1 )
            {
                split ( root, tot, left, o );
                remove ( left );
                root = o;
            }
            else
            {
                split ( root, pos-1, left, o );
                split ( o, tot, mid, right );
                remove ( mid );
                root = Merge ( left, right );
            }
        }
        else if ( op[0] == 'M' )
        {
            if ( strcmp ( op, "MAKE-SAME" ) == 0 )
            {
                scanf ( "%d%d%d", &pos, &tot, &x );
                if ( tot == 0 )
                    continue ;
                if ( pos == 1 )
                {
                    split ( root, tot, left, o );
                    left->modify ( x );
                    root = Merge ( left, o );
                }
                else
                {
                    split ( root, pos-1, left, o );
                    split ( o, tot, mid, right );
                    mid->modify ( x );
                    root = Merge ( Merge ( left, mid ), right );
                }
            }
            else
                printf ( "%d\n", root->mv );
        }
        else if ( op[0] == 'R' )
        {
            scanf ( "%d%d", &pos, &tot );
            if ( pos == 1 )
            {
                split ( root, tot, left, o );
                left->reverse ( );
                root = Merge ( left, o );
            }
            else
            {
                split ( root, pos-1, left, o );
                split ( o, tot, mid, right );
                mid->reverse ( );
                root = Merge ( Merge ( left, mid ), right );
            }
        }
        else
        {
            scanf ( "%d%d", &pos, &tot );
            if ( tot == 0 ) //tot为0处理
            {
                printf ( "0\n" );
                continue ;
            }
            if ( pos == 1 )
            {
                split ( root, tot, left, o );
                printf ( "%d\n", left->sum );
                root = Merge ( left, o );
            }
            else
            {
                split ( root, pos-1, left, o );
                split ( o, tot, mid, right );
                printf ( "%d\n", mid->sum );
                root = Merge ( Merge ( left, mid ), right );
            }
        }
        //print ( root );
        //printf ( "\n" );
    }
}
int main ( )
{
    solve ( );
    return 0;
}

UVaLive 3961 HDU 1890

这题主要是将某个点旋转至某个节点的操作,所以需要保存父节点。

数组实现

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <utility>
#include <map>
#include <set>
#include <queue>
#include <vector>
#include <iostream>
#include <stack>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-6
#define CLR( a, v ) memset ( a, v, sizeof ( a ) )
#define LL long long
#define DBUG printf ( "here!!!\n" )
#define rep( i, a, b ) for ( int i = ( a ); i < ( b ); i ++ )
#define PB push_back
#define ULL unsigned long long
#define PI acos ( -1.0 )
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define lowbit( x ) ( ( x )&( -x ) )
#define CASE int Test; scanf ( "%d", &Test ); for ( int cas = 1; cas <= Test; cas ++ )
#define ALL( x ) x.begin ( ), x.end ( )
#define INS( x ) x, x.begin ( )
#define Key_value ch[ ch[root][1] ][0]
typedef pair < int, int > Pii;
typedef pair < double, double > Pdd;
typedef set < int > Set;
const int maxn = 100005;
int read_int ( )
{
    int res = 0;
    int ch;
    while ( ( ch = getchar ( ) ) && ! ( ch >= '0' && ch <= '9' ) )
    {
        if ( ch == -1 )
            return -1;
    }
    while ( ch >= '0' && ch <= '9' )
    {
        res = res*10+( ch-'0' );
        ch = getchar ( );
    }
    return res;
}
int ch[maxn][2], cnt[maxn], rev[maxn], pre[maxn];
int tot, pp[maxn], root, key[maxn], mp[maxn];
void newNode ( int &r, int fa, int k )
{
    r = ++ tot;
    pre[r] = fa;
    ch[r][0] = ch[r][1] = rev[r] = 0;
    key[r] = k;
}
void PushUP ( int x )
{
    cnt[x] = cnt[ ch[x][0] ]+cnt[ ch[x][1] ]+1;
}
void Rever ( int x )
{
    if ( x == 0 )
        return ;
    swap ( ch[x][0], ch[x][1] );
    rev[x] ^= 1;
}
void PushDown ( int x )
{
    if ( rev[x] )
    {
        Rever ( ch[x][0] );
        Rever ( ch[x][1] );
        rev[x] = 0;
    }
}
void Build ( int &x, int L, int R, int fa )
{
    if ( L >= R )
    {
        x = 0;
        return ;
    }
    int M = ( L+R ) >> 1;
    newNode ( x, fa, pp[M] );
    mp[ pp[M] ] = x;
    Build ( ch[x][0], L, M, x );
    Build ( ch[x][1], M+1, R, x );
    PushUP ( x );
}
Pii a[maxn];
int cmp ( Pii x, Pii y )
{
    return x.first < y.first || x.first == y.first && x.second < y.second;
}
void Init ( int n )
{
    root = tot = 0;
    for ( int i = 1; i <= n; i ++ )
    {
        scanf ( "%d", &a[i].first );
        a[i].second = i;
    }
    sort ( a+1, a+1+n, cmp );
    for ( int i = 1; i <= n; i ++ )
        pp[ a[i].second ] = i;
    ch[root][0] = ch[root][1] = cnt[root] = rev[root] = pre[root] = 0;
    newNode ( root, 0, -1 );
    newNode ( ch[root][1], root, -1 );
    Build ( Key_value, 1, n+1, ch[root][1] );
    PushUP ( ch[root][1] );
    PushUP ( root );
}
void Rotate ( int x, int k )
{
    int y = pre[x];
    ch[y][k^1] = ch[x][k];
    if ( ch[x][k] )
        pre[ ch[x][k] ] = y;
    ch[x][k] = y;
    if ( pre[y] )
        ch[ pre[y] ][ ch[ pre[y] ][1] == y ] = x;
    pre[x] = pre[y];
    pre[y] = x;
    PushUP ( y );
    PushUP ( x );
}
void Splay ( int x, int goal )
{
    PushDown ( x );
    while ( pre[x] != goal )
    {
        int y = pre[x];
        PushDown ( y );
        PushDown ( x );
        if ( pre[y] == goal )
            Rotate ( x, ch[y][0] == x );
        else
        {
            int z = pre[y];
            PushDown ( z );
            PushDown ( y );
            PushDown ( x );
            int d = ch[z][1] == y, d2 = ch[y][1] == x;
            if ( d == d2 )
                Rotate ( x, d^1 );
            else
                Rotate ( x, d );
            Rotate ( x, d^1 );
        }
    }
    PushUP ( x );
    if ( goal == 0 )
        root = x;
}
int Get_Kth ( int x, int k )
{
    PushDown ( x ); //注意需要向下更新否则中间运行会有问题
    int d = cnt[ ch[x][0] ]+1;
    if ( d == k )
        return x;
    if ( d > k )
        return Get_Kth ( ch[x][0], k );
    return Get_Kth ( ch[x][1], k-d );
}
void solve ( )
{
    int n;
    //freopen ( "in0.in", "r", stdin );
    while ( ~ scanf ( "%d", &n ), n )
    {
        Init ( n );
        for ( int i = 1; i <= n; i ++ )
        {
            Splay ( mp[i], root );
            printf ( i == 1 ? "%d" : " %d", i+cnt[Key_value] );
            Rever ( Key_value );
            Splay ( Get_Kth( ch[root][1], cnt[Key_value]+2 ), root );
            Splay ( Get_Kth ( Key_value, cnt[Key_value] ), ch[root][1] );
            int x = ch[Key_value][0];
            if ( x )
                pre[x] = ch[root][1];
            Key_value = x;
            PushUP ( ch[root][1] );
            PushUP ( root );
        }
        printf ( "\n" );
    }
}
int main ( )
{
    solve ( );
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值