伸展树和名次树基本上差不多,直接上模板。
链表实现
#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;
}