[NOI2005]维修数列
中文题,题意不解释。。
平衡树模板,做法不解释。。就看你模板是否够硬了。。
无论在哪种数据结构中,我对push_down( int rt )的理解是,rt节点的信息已经是真实的,而其子节点并不一定真实,因为当前节点上可能还有延迟标记,因而,其作用是将当前节点的延迟信息推送到子节点上,使其子节点真实。
先来发伸展树:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std ;
const int maxn = 1000502 ;
const int INF = 1111111111 ;
int size[maxn] , fa[maxn] , son[2][maxn] ;
int sum[maxn] , col[maxn] , val[maxn] , re[maxn] ;
int mm[maxn] , rm[maxn] , lm[maxn] , num[maxn] ;
int sta[maxn] , top ;
int tot , n ;
int fun()
{
char ch;
int flag=1,a=0;
while(ch=getchar())
{
if((ch>='0'&&ch<='9')||ch=='-')break;
}
if(ch=='-')flag=-1;
else a=ch-'0';
while(ch=getchar())
{
if(ch>='0'&&ch<='9')a=10*a+ch-'0';
else break;
}
return flag*a;
}
int max ( int a , int b ) { return a > b ? a : b ; }
void push_up(int x){
int l=son[0][x],r=son[1][x];
size[x]=size[l]+size[r]+1;
sum[x]=sum[l]+sum[r]+val[x];
lm[x]=max(lm[l],sum[l]+val[x]+max(0,lm[r]));
rm[x]=max(rm[r],sum[r]+val[x]+max(0,rm[l]));
mm[x]=max(0,rm[l])+val[x]+max(0,lm[r]);
mm[x]=max(mm[l],max(mm[r],mm[x]));
}
void up_rev ( int rt ) {
if ( !rt ) return ;
swap ( son[0][rt] , son[1][rt] ) ;
swap ( lm[rt] , rm[rt] ) ;
col[rt] ^= 1 ;
}
void up_mak ( int rt , int v ) {
if ( !rt ) return ;
re[rt] = val[rt] = v ;
sum[rt] = val[rt] * size[rt] ;
mm[rt] = lm[rt] = rm[rt] = ( val[rt] > 0 ? sum[rt] : val[rt] ) ;
}
void push_down ( int rt ) {
int ls = son[0][rt] , rs = son[1][rt] ;
if ( col[rt] ) {
up_rev ( ls ) ;
up_rev ( rs ) ;
col[rt] = 0 ;
}
if ( re[rt] != INF ) {
up_mak ( ls , re[rt] ) ;
up_mak ( rs , re[rt] ) ;
re[rt] = INF ;
}
}
void down ( int x ) {
if ( !x ) return ;
down ( fa[x] ) ;
push_down ( x ) ;
}
void rot ( int x , int c ) {
int y = fa[x] , z = fa[y] ;
push_down ( y ) , push_down ( x ) ;
son[!c][y] = son[c][x] ;
if ( son[c][x] ) fa[son[c][x]] = y ;
son[c][x] = y , fa[y] = x ;
fa[x] = z ;
if ( z ) {
if ( y == son[0][z] ) son[0][z] = x ;
else son[1][z] = x ;
}
push_up ( y ) ;
}
void splay ( int x , int to ) {
while ( fa[x] != to ) {
if ( fa[fa[x]] == to ) rot ( x , x == son[0][fa[x]] ) ;
else {
int y = fa[x] , z = fa[y] ;
if ( x == son[0][y] ) {
if ( y == son[0][z] ) rot ( y , 1 ) , rot ( x , 1 ) ;
else rot ( x , 1 ) , rot ( x , 0 ) ;
}
else {
if ( y == son[1][z] ) rot ( y , 0 ) , rot ( x , 0 ) ;
else rot ( x , 0 ) , rot ( x , 1 ) ;
}
}
}
push_up ( x ) ;
}
int find ( int k , int rt ) {
push_down ( rt ) ;
int cnt = 0 ;
if ( son[0][rt] ) cnt += size[son[0][rt]] ;
if ( cnt + 1 == k ) return rt ;
if ( cnt >= k ) return find ( k , son[0][rt] ) ;
return find ( k - cnt - 1 , son[1][rt] ) ;
}
void init ( int p ) {
size[p] = 1 ;
son[0][p] = son[1][p] = fa[p] = 0 ;
mm[p] = lm[p] = rm[p] = -INF ;
val[p] = -INF , re[p] = INF , col[p] = 0 ;
}
int new_node () {
tot ++ ;
init ( tot ) ;
return tot ;
}
int build ( int l , int r ) {
if ( l > r ) return 0 ;
int m = ( l + r ) >> 1 ;
int p = new_node () ;
if ( m != 0 && m != n + 1 ) val[p] = num[m] ;
son[0][p] = build ( l , m - 1 ) ;
if ( son[0][p] ) fa[son[0][p]] = p ;
son[1][p] = build ( m + 1 , r ) ;
if ( son[1][p] ) fa[son[1][p]] = p ;
push_up ( p ) ;
return p ;
}
void reuse ( int rt ) {
sta[++top] = rt ;
if ( son[0][rt] ) reuse ( son[0][rt] ) ;
if ( son[1][rt] ) reuse ( son[1][rt] ) ;
init ( rt ) ;
}
int add[maxn] ;
int insert ( int rt ) {
int pos , t , i , last ;
pos = fun () ; t = fun() ;
if ( t <= 0 ) return rt ;
pos ++ ;
int temp = find ( pos , rt ) ;
splay ( temp , 0 ) ;
rt = temp ;
temp = find ( pos + 1 , rt ) ;
splay ( temp , rt ) ;
for ( i = 1 ; i <= t ; i ++ ) {
add[i] = ( top ? sta[top--] : new_node () ) ;
val[add[i]] = fun () ;
}
son[1][add[t]] = temp , fa[temp] = add[t] ;
push_up ( add[t] ) ;
for ( i = t - 1 ; i >= 1 ; i -- ) {
son[1][add[i]] = add[i+1] ;
fa[add[i+1]] = add[i] ;
push_up ( add[i] ) ;
}
son[1][rt] = add[1] , fa[add[1]] = rt ;
push_up ( rt ) ;
return rt ;
}
int del ( int rt ) {
int pos , t ;
pos = fun () ; t = fun () ;
if ( t <= 0 ) return rt ;
pos ++ ;
int temp = find ( pos - 1 , rt ) ;
splay ( temp , 0 ) ;
rt = temp ;
temp = find ( pos + t , rt ) ;
splay ( temp , rt ) ;
reuse ( son[0][temp] ) ;
son[0][temp] = 0 ;
push_up ( temp ) ;
push_up ( rt ) ;
return rt ;
}
int make ( int rt ) {
int pos , t , fix ;
pos = fun () ; t = fun () ; fix = fun () ;
if ( t <= 0 ) return rt ;
pos ++ ;
int temp = find ( pos - 1 , rt ) ;
splay ( temp , 0 ) ;
rt = temp ;
temp = find ( pos + t , rt ) ;
splay ( temp , rt ) ;
int x = son[0][temp] ;
up_mak ( x , fix ) ;
push_up ( temp ) ;
push_up ( rt ) ;
return rt ;
}
int rev ( int rt ) {
int pos , t ;
pos = fun () ; t = fun () ;
if ( t <= 1 ) return rt ;
pos ++ ;
int temp = find ( pos - 1 , rt ) ;
splay ( temp , 0 ) ;
rt = temp ;
temp = find ( pos + t , rt ) ;
splay ( temp , rt ) ;
int x = son[0][temp] ;
up_rev ( x ) ;
push_up ( temp ) ;
push_up ( rt ) ;
return rt ;
}
int get ( int rt ) {
int pos , t ;
pos = fun () ; t = fun () ;
if ( t <= 0 ) {
puts ( "0" ) ;
return rt ;
}
pos ++ ;
int temp = find ( pos - 1 , rt ) ;
splay ( temp , 0 ) ;
rt = temp ;
temp = find ( pos + t , rt ) ;
splay ( temp , rt ) ;
printf ( "%d\n" , sum[son[0][temp]] ) ;
return rt ;
}
int max_sum ( int rt ) {
printf ( "%d\n" , mm[rt] ) ;
return rt ;
}
char op[111] ;
int main () {
int m , i ;
// freopen ( "sequence8.in" , "r" , stdin ) ;
// freopen ( "ans1.txt" , "w" , stdout ) ;
while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
tot = top = 0 ;
init ( 0 ) ;
size[0] = sum[0] = 0 ;
for ( i = 1 ; i <= n ; i ++ ) {
num[i] = fun () ;
}
int root = build ( 0 , n + 1 ) ;
while ( m -- ) {
scanf ( "%s" , op ) ;
if ( op[2] == 'S' ) root = insert ( root ) ;
else if ( op[2] == 'L' ) root = del ( root ) ;
else if ( op[2] == 'K' ) root = make ( root ) ;
else if ( op[2] == 'V' ) root = rev ( root ) ;
else if ( op[2] == 'T' ) root = get ( root ) ;
else root = max_sum ( root ) ;
}
}
}
再来一发treap
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <map>
#include <math.h>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <stdlib.h>
#include <time.h>
#define ll int
using namespace std;
const int INF = 1111111111 ;
int fun()
{
char ch;
int flag=1,a=0;
while(ch=getchar())
{
if((ch>='0'&&ch<='9')||ch=='-')break;
}
if(ch=='-')flag=-1;
else a=ch-'0';
while(ch=getchar())
{
if(ch>='0'&&ch<='9')a=10*a+ch-'0';
else break;
}
return flag*a;
}
const int maxn = 1020001 ;
int num[maxn] ;
struct Treap {
int c[2][maxn] , size[maxn] , tot ;
ll sum[maxn] , val[maxn] , col[maxn] , mx[maxn] , lm[maxn] , rm[maxn] ;
int f[maxn] , sta[maxn] , top , p[maxn] ;
void init () {
tot = top = 0 ;
mx[0] = lm[0] = rm[0] = - INF ;
}
void push_up ( int x ) {
int l=c[0][x],r=c[1][x];
size[x]=size[l]+size[r]+1;
sum[x]=sum[l]+sum[r]+val[x];
lm[x]=max(lm[l],sum[l]+val[x]+max(0,lm[r]));
rm[x]=max(rm[r],sum[r]+val[x]+max(0,rm[l]));
mx[x]=max(0,rm[l])+val[x]+max(0,lm[r]);
mx[x]=max(mx[l],max(mx[r],mx[x]));
}
void rev ( int rt ) {
if ( !rt ) return ;
f[rt] ^= 1 ;
swap ( lm[rt] , rm[rt] ) ;
swap ( c[0][rt] , c[1][rt] ) ;
}
void color ( int rt , int v ) {
if ( !rt ) return ;
mx[rt] = val[rt] = col[rt] = v ;
sum[rt] = size[rt] * v ;
if ( v > 0 ) mx[rt] = lm[rt] = rm[rt] = size[rt] * v ;
else lm[rt] = rm[rt] = 0 ;
}
void push_down ( int rt ) {
int ls = c[0][rt] , rs = c[1][rt] ;
if ( f[rt] ) {
rev ( ls ) ;
rev ( rs ) ;
f[rt] = 0 ;
}
if ( col[rt] != INF ) {
color ( ls , col[rt] ) ;
color ( rs , col[rt] ) ;
col[rt] = INF ;
}
}
int ran ( int rt ) {
static int rans = 123456789 ;
return rans += rans << 2 | 1 ;
}
int new_node ( ll v ) {
int temp ;
if ( top ) temp = sta[top--] ;
else temp = ++ tot ;
p[temp] = ran ( temp ) ;
size[temp] = 1 ;
val[temp] = sum[temp] = mx[temp] = v ;
c[0][temp] = c[1][temp] = f[temp] = 0 ;
col[temp] = INF ;
lm[temp] = rm[temp] = max ( (ll) 0 , v ) ;
return temp ;
}
int merge ( int x , int y ) {
if ( !x ) return y ;
if ( !y ) return x ;
push_down ( x ) ; push_down ( y ) ;
if ( p[x] < p[y] ) {
c[1][x] = merge ( c[1][x] , y ) ;
push_up ( x ) ;
return x ;
}
c[0][y] = merge ( x , c[0][y] ) ;
push_up ( y ) ;
return y ;
}
void split ( int rt , int &x , int &y , int k ) {
if ( k == 0 ) { x = 0 , y = rt ; return ; }
push_down ( rt ) ;
int ls = c[0][rt] , rs = c[1][rt] ;
if ( size[ls] + 1 == k ) {
x = rt , y = c[1][rt] ;
c[1][rt] = 0 ;
push_up ( rt ) ;
return ;
}
if ( size[ls] + 1 < k ) {
split ( c[1][rt] , x , y , k - size[ls] - 1 ) ;
c[1][rt] = x ; x = rt ;
push_up ( rt ) ;
return ;
}
split ( c[0][rt] , x , y , k ) ;
c[0][rt] = y ; y = rt ;
push_up ( rt ) ;
}
int Insert ( int rt , int l , int v ) {
if ( v <= 0 ) return rt ;
int x , y , temp = 0 ;
temp = build ( 1 , v ) ;
if ( !rt ) return temp ;
split ( rt , x , y , l ) ;
temp = merge ( x , temp ) ; temp = merge ( temp , y ) ;
return temp ;
}
void del ( int rt ) {
if ( !rt ) return ;
sta[++top] = rt ;
del ( c[0][rt] ) ;
del ( c[1][rt] ) ;
}
int Del ( int rt , int l , int k ) {
int x , y , temp = 0 ;
split ( rt , x , temp , l - 1 ) ;
split ( temp , temp , y , k ) ;
del ( temp ) ;
rt = merge ( x , y ) ;
return rt ;
}
int Mk_sm ( int rt , int l , int k , int v ) {
int x , y , temp = 0 ;
split ( rt , x , temp , l - 1 ) ;
split ( temp , temp , y , k ) ;
color ( temp , v ) ;
temp = merge ( x , temp ) ; temp = merge ( temp , y ) ;
return temp ;
}
int Reverse ( int rt , int l , int k ) {
int x , y , temp ;
split ( rt , x , temp , l - 1 ) ;
split ( temp , temp , y , k ) ;
rev ( temp ) ;
temp = merge ( x , temp ) ; temp = merge ( temp , y ) ;
return temp ;
}
ll Get_sum ( int &rt , int l , int k ) {
int x , y , temp ;
split ( rt , x , temp , l - 1 ) ;
split ( temp , temp , y , k ) ;
ll ans = sum[temp] ;
temp = merge ( x , temp ) ; temp = merge ( temp , y ) ;
rt = temp ;
return ans ;
}
ll Max_sum ( int rt ) {
return mx[rt] ;
}
int build ( int l , int r ) {
if ( l > r ) return 0 ;
int mid = l + r >> 1 ;
int temp = new_node ( num[mid] ) ;
c[0][temp] = build ( l , mid - 1 ) ;
c[1][temp] = build ( mid + 1 , r ) ;
push_up ( temp ) ;
return temp ;
}
void print ( int rt ) {
if ( !rt ) return ;
print ( c[0][rt] ) ;
printf ( "%d " , val[rt] ) ;
print ( c[1][rt] ) ;
}
} tree ;
int main() {
int n , m , i , j , k , l , c ;
while ( scanf ( "%d%d" , &n , &m ) != EOF ) {
tree.init () ;
int rt = 0 ;
for ( i = 1 ; i <= n ; i ++ )
num[i] = fun () ;
rt = tree.build ( 1 , n ) ;
char op[1111] ;
while ( m -- ) {
scanf ( "%s" , op ) ;
if ( op[0] == 'I' ) {
j = fun () ; k = fun () ;
for ( i = 1 ; i <= k ; i ++ ) {
num[i] = fun () ;
}
rt = tree.Insert ( rt ,j , k ) ;
}
else if ( op[0] == 'D' ) {
j = fun () ; k = fun () ;
if ( k < 0 ) continue ;
rt = tree.Del ( rt , j , k ) ;
}
else if ( op[0] == 'M' && op[1] == 'A' && op[2] == 'K' ) {
j = fun () ; k = fun () ; c = fun () ;
if ( k <= 0 ) continue ;
rt = tree.Mk_sm ( rt , j , k , c ) ;
}
else if ( op[0] == 'G' ) {
j = fun () ; k = fun () ;
if ( k <= 0 ) {
puts ( "0" ) ;
continue ;
}
printf ( "%d\n" , tree.Get_sum ( rt , j , k ) ) ;
}
else if ( op[0] == 'R' ) {
j = fun () ; k = fun () ;
if ( k <= 1 ) continue ;
rt = tree.Reverse ( rt , j , k ) ;
}
else {
printf ( "%d\n" , tree.Max_sum ( rt ) ) ;
}
}
}
return 0;
}