I HATE IT 伸展树

View Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <time.h>

using namespace std;

int left[200100], right[200100], maxn[200100], pf[200100], value[200100],root; //值为-1的点表示该结点为空

void update(int n)
{
if( n == -1 )
return;
else if( left[n] != -1 && right[n] != -1)
maxn[n] = max(max(maxn[left[n]], maxn[right[n]]), value[n]);
else if( left[n] != -1)
maxn[n] = max(maxn[left[n]], value[n]);
else if( right[n] != -1)
maxn[n] = max(maxn[right[n]], value[n]);
else
maxn[n] = value[n];
}
//右旋
inline void zig( int n )
{
int m = pf[n];
left[m] = right[n];
pf[right[n]] = m;
right[n] = m;
if(left[pf[m]] == m )
left[pf[m]] = n;
else
right[pf[m]] = n;
update(m);
update(n);
pf[n] = pf[m];
pf[m] = n;
}

//左旋
inline void zag( int n )
{
int m = pf[n];
right[m] = left[n];
pf[left[n]] = m;
left[n] = m;
if(left[pf[m]] == m )
left[pf[m]] = n;
else
right[pf[m]] = n;
update(m);
update(n);
pf[n] = pf[m];
pf[m] = n;

}



inline int splay(int n, int p)
{
while( pf[n] != p )
{
if( pf[pf[n]] == p )
{
if( n == left[pf[n]])
zig(n);
else
zag(n);

}
else
{
if( left[pf[pf[n]]] == pf[n] )
{
if( left[pf[n]] == n )
{
zig(pf[n]);
zig(n);
}
else
{
zag(n);
zig(n);
}
}
else if(right[pf[pf[n]]] == pf[n])
{
if( right[pf[n]] == n )
{
zag(pf[n]);
zag(n);
}
else
{
zig(n);
zag(n);
}
}
}
}
return n;

}


inline void insert(int head, int n, int f, int flag) //头结点序号,插入的结点序号,以及它的祖先
{
if( head == -1 )
{
if( flag == 0 )
root = n;
else if( flag == 1)
left[f] = n;
else if( flag == 2 )
right[f] = n;
pf[n] = f;
right[n] = -1;
left[n] = -1;
maxn[n] = value[n];
}
else
{
if(head > n )
{
if( left[head] == -1 )
flag = 1;
insert(left[head], n, head, flag);
}
else
{
if( left[head] == -1 )
flag = 2;
insert(right[head],n, head, flag);
}
}
update(head);
}


void preordertravel( int n )
{
if ( n != -1 ) {
printf("%d 的 父亲节点是 %d\n",n,pf[n]);
preordertravel(left[n]);
preordertravel(right[n]);
}
}

int modify( int p, int a, int b)
{
p = splay(a,-1);
value[a] = b;
update(a);
return p;
}
int main( )
{
int N,M, a, b;
char str[100];
while ( scanf("%d%d", &N, &M) != EOF )
{
root = -1;
insert(root,0,-1,0);
insert(root,N + 1,-1, 0);
value[0] = value[N + 1] = 0;
for( int i = 1; i <= N; i++)
{
scanf("%d",&value[i]);
insert(root, i, -1, 0);
root = splay(i,-1);
}
// preordertravel( root );
for( int i = 1; i <= M; i++)
{
scanf("%s%d%d",str, &a, &b);
if( str[0] == 'U' )
{
modify(root, a, b);
continue;
}
root = splay(a - 1, -1);
right[root]= splay(b + 1, root);
printf("%d\n",maxn[left[right[root]]]);
}
}
return 0;
}
/*
10
10
43 12 54 76 432
298 12894 1 34 5
10 的 父亲节点是 -1
9 的 父亲节点是 10
8 的 父亲节点是 9
7 的 父亲节点是 8
6 的 父亲节点是 7
5 的 父亲节点是 6
4 的 父亲节点是 5
3 的 父亲节点是 4
2 的 父亲节点是 3
1 的 父亲节点是 2
0 的 父亲节点是 1
11 的 父亲节点是 10
*/

利用splay树维护区间信息,求解区间相关量。

当要求解区间【a,b]信息时,可把a-1伸展至根节点, b + 1伸展至根节点右孩子.

posted on 2012-03-05 00:54  more think, more gains  阅读(175)  评论(0编辑  收藏  举报

导航