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

来源:互联网 发布:纯js 的时间控件 编辑:程序博客网 时间:2024/05/16 14:55

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

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
原创粉丝点击