模板:区间反转,区间加某一个值,区间求最大值
坑点:首尾各加上两个节点后,注意第一个新加点的初值。
这个东西应该叫名次树吧,写完这个东西最大的体会就是,树上每个节点的标号其实就是人们思维上那个点应该出现的value的索引值,怎么标并不重要。
#include
typedef long long LL;
typedef int lint;
using namespace std;
const LL maxn = 100000+10;
const LL inf= 0x7fffffff;
LL a[maxn];
struct Splay{
lint fa[maxn],sz[maxn],ch[maxn][2],root,flag[maxn];
LL val[maxn],laz[maxn],Max[maxn];
void init( ){
memset( fa,0,sizeof( fa ) );
memset( ch,0,sizeof( ch ) );
memset( sz,0,sizeof(sz ) );
memset( laz,0,sizeof( laz ) );
memset( flag,0,sizeof( flag ) );
}
lint get( lint x ){
return x == ch[ fa[x] ][1];
}
void push_up( lint x ){
sz[x] = sz[
ch[x][0] ] + sz[ ch[x][1] ] + 1;
Max[x] = max(max( Max[ ch[x][0] ],Max[ ch[x][1] ] ) ,val[ x ]);
}
void push_down1( lint x ){
lint lc = ch[x][0];
lint rc = ch[x][1];
if( lc ){
flag[ lc ] ^= 1;
swap( ch[lc][0],ch[lc][1] );
}
if( rc ){
flag[ rc ] ^= 1;
swap( ch[rc][0],ch[rc][1] );
}
flag[x] = 0;
}
void push_down2( lint x ){
lint lc = ch[x][0];
lint rc = ch[x][1];
if( lc ){
laz[lc] += laz[x];
val[lc] += laz[x];
Max[lc] += laz[x];
}
if( rc ){
laz[rc] += laz[x];
val[rc] += laz[x];
Max[rc] += laz[x];
}
laz[x] = 0;
}
void Rotate( lint x ){
lint f = fa[x],ff = fa[f],d = get(x);
if(ff)ch[ff][ get(f) ] = x; fa[x] = ff;
if( ch[x][!d] )fa[ch[x][!d]] = f;ch[f][d] = ch[x][!d];
fa[f] = x; ch[x][!d] = f;
push_up( f );
push_up( x );
}
lint Find( lint x,lint k ){
if( flag[x] ) push_down1(x);
if( laz[x] ) push_down2(x);
lint lc = ch[x][0],rc = ch[x][1];
if( k ==sz[ lc ] + 1 ){
return x;
}else if( k <= sz[lc] ){
return Find( lc,k );
}else{
return Find( rc,k - sz[lc]-1 );
}
}
void splay( lint x,lint y = 0 ){
lint p = x;
vector ve;
while( p && p != y ) { ve.push_back( p ); p = fa[p];}
for( lint i = ve.size()-1;i >= 0;i-- ){
if( flag[ ve[i] ] )push_down1( ve[i] );
if( laz[ ve[i] ] ) push_down2( ve[i] );
}
while(fa[x] != y ){
if( fa[ fa[x] ] == y ){
Rotate(x);
}else{
if( get( x ) == get( fa[x] ) ) Rotate( fa[x] );
else Rotate( x );
Rotate( x );
}
}
if(!y)root = x;
}
void Reverse( lint x,lint y ){
lint u = Find( root,x-1 );
lint v = Find( root,y+1 );
splay( u );
splay( v,u );
lint lc = ch[v][0];
flag[ lc ] ^= 1LL;
swap( ch[lc][0],ch[lc][1] );
}
void change( LL l,LL r,LL v ){
lint x = Find( root,l-1 );
lint y = Find( root,r+1 );
splay( x );
splay( y,x );
lint lc = ch[y][0];
laz[ lc ] += v;
val[ lc ] += v;
Max[lc] += v;
}
lint build( lint l,lint r ){
if( l > r ) return 0;
lint mid = l + r >> 1;
val[mid] = a[mid];
Max[mid] = val[mid];
ch[mid][0] = build( l,mid-1 ); if( ch[mid][0] )fa[ ch[mid][0] ] = mid;
ch[mid][1] = build( mid+1,r ); if( ch[mid][1] )fa[ ch[mid][1] ] = mid;
push_up( mid );
return mid;
}
/* void dfs( LL x ){
if(flag[x]) push_down(x);
if( ch[x][0] ) dfs( ch[x][0] );
if( x != 1 && x != n+2 )
printf("%lld ",val[x]);
if( ch[x][1] ) dfs( ch[x][1] );
}*/
LL ask( lint l,lint r ){
lint x = Find(root,l-1);
lint y = Find( root,r+1 );
splay(x);
splay( y,x );
lint lc = ch[y][0];
return Max[lc];
}
}g;
int main(){
lint n,m,q,x,y,v;
scanf("%d%d",&n,&m);
n += 2;
for( lint i = 1;i <= n;i++ ) a[i] = 0;
a[1] = -inf; a[n] = -inf;
g.Max[0] = g.val[0] = -inf;
//g.init();
g.root = g.build(1,n);
for( lint i = 1;i <= m;i++ ){
scanf("%d",&q);
if( q == 1 ){
scanf("%d%d%d",&x,&y,&v);
x++;y++;
g.change(x,y,v);
}else if( q == 2 ){
scanf("%d%d",&x,&y);
x++;y++;
g.Reverse(x,y);
}else{
scanf("%d%d",&x,&y);
x++; y++;
LL ans = g.ask( x,y );
printf("%d\n",ans);
}
}
return 0;
}