splay学习
先记录一下我自己打的\(splay\)模板(综合多个\(blog\),巨简洁)
甚至我自己加入了自动机元素(在\(x\)节点值为\(dlt\)应该到达哪个儿子)
好写好调,墙烈案例
ps. 需要注意的:
- \(spinup\)中的\(z\)是\(ch [z][sk(y)]\),而不是\(ch [z][k]\)
- 只要有\(size\)改动就要\(splay\)维护\(size\)正确性
- 只要没事就要\(splay\) 一下。
code
#include <cstring>
#include <algorithm>
#include <cstdio>
#define mp make_pair
#define R register int
#define int long
#define printf Ruusupuu = printf
int Ruusupuu ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
typedef pair< int , int > PI ;
const int N = 1e5 + 10 ;
const int Inf = 0x3f3f3f3f ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , opt ;
int root , znt , ch [N][2] , fa [N] , son [N] , val [N] , size [N] ;
#define zt( x ) son [x] = ( son [ch [x][0]] + son [ch [x][1]] + size [x] )
#define sk( x ) ( x == ch [fa [x]][1] )
#define tr( x , dlt ) ch [x][dlt > val [x]]
inline void spinup( int x ){
R y = fa [x] , z = fa [y] , k = sk( x ) ;
ch [z][sk(y)] = x , fa [x] = z ;
ch [y][k] = ch [x][k ^ 1] , fa [ch [x][k ^ 1]] = y ;
ch [x][k ^ 1] = y , fa [y] = x ;
zt( y ) , zt( x ) ;
}
inline void splay( int x , int pos ){
while( fa [x] != pos ){
R y = fa [x] ; R z = fa [y] ;
if( z != pos ) sk( x ) ^ sk ( y ) ? spinup( x ) : spinup( y ) ; //on the same line ? spinup( y ) : spinup( x ) ;
spinup( x ) ;
} if( !pos ) root = x ;
}
inline void ins( int dlt ){
R now = root , fh = 0 ;
while( now && val [now] != dlt ) fh = now , now = tr( now , dlt ) ;
if( now ) size [now] ++ ;
else {
now = ++ znt ;
if( fh ) tr( fh , dlt ) = now ;
size [now] = son [now] = 1 ;
fa [now] = fh , val [now] = dlt ;
}
splay( now , 0 ) ;
}
inline void find( int dlt ){
R now = root ; if( !now ) return ;
while( tr( now , dlt ) && val [now] != dlt )
now = tr( now , dlt ) ;
splay( now , 0 ) ;
}
inline int ngr( int dlt , bool fg ){
find( dlt ) ; R now = root ;
if( val [now] != dlt && ( fg ^ ( val [now] < dlt ) ) ) return now ;
now = ch [now][fg] ;
while( ch [now][fg ^ 1] ) now = ch [now][fg ^ 1] ;
return now ;
}
inline void del( int dlt ){
int pre = ngr( dlt , 0 ) , nxt = ngr( dlt , 1 ) ;
splay( pre , 0 ) , splay( nxt , pre ) ;
int now = ch [nxt][0] ;
if( size [now] > 1 ) size [now] -- , splay( now , 0 ) ;
else ch [nxt][0] = 0 , splay( nxt , 0 ) ;
}
inline int rk( int rank ){
int now = root ;
if( son [now] < rank ) return 0 ;
while( 1 ){
int nxt = ch [now][0] ;
if( size [now] + son [nxt] < rank ) rank -= ( size [now] + son [nxt] ) , now = ch [now][1] ;
else if( son [nxt] >= rank ) now = nxt ;
else { splay( now , 0 ) ; return val [now] ; }
}
}
void sc(){
n = read() ;
}
void work(){
ins( -Inf ) , ins( Inf ) ;
while( n -- ){
opt = read() ;
if( opt == 1 ) ins( read() ) ;
else if( opt == 2 ) del( read() ) ;
else if( opt == 3 ) find( read() ) , printf( "%ld\n" , son [ch [root][0]] ) ;
else if( opt == 4 ) printf( "%ld\n" , rk( read() + 1 ) ) ;
else if( opt == 5 ) printf( "%ld\n" , val [ngr( read() , 0 )] ) ;
else if( opt == 6 ) printf( "%ld\n" , val [ngr( read() , 1 )] ) ;
}
}
signed main(){
sc() ;
work() ;
return 0 ;
}
应某大佬觉得我的板子过不了数据加强版,所以更新了一下,其实很简单,只需要额外写一个函数\(ranks\),因为\(find\)函数如果找不到对应的值,就会把这个值的前驱或者后继搞到根,所以只需要特判一下就行了。
其实两份代码的差别只有一个函数
inline int ranks( int dlt ){
find( dlt ) ;
R now = root ;
if( val [now] < dlt ) now = ngr( val [now] , 1 ) ;
return son [ch [now][0]] ;
}
code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define R register int
#define int long
#define scanf Ruusupuu = scanf
#define printf Ruusupuu = printf
#define freopen rsp_5u = freopen
int Ruusupuu ;
FILE * rsp_5u ;
using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 2e6 + 10 ;
const int Inf = 1 << 30 ;
inline void of(){ freopen( "in.in" , "r" , stdin ) , freopen( "out.out" , "w" , stdout ) ; }
inline void cf(){ fclose( stdin ) , fclose( stdout ) ; }
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , m , opt , x , last , ans ;
int size [N] , son [N] , val [N] , fa [N] , ch [N][2] , root , znt ;
#define zt( x ) son [x] = son [ch [x][0]] + son [ch [x][1]] + size [x]
#define sk( x ) ( x == ch [fa [x]][1] )
#define tr( x , dlt ) ch [x][dlt > val [x]]
inline void spinup( int x ){
R y = fa [x] , z = fa [y] , k = sk( x ) ;
ch [z][sk(y)] = x , fa [x] = z ;
ch [y][k] = ch [x][k ^ 1] , fa [ch [x][k ^ 1]] = y ;
ch [x][k ^ 1] = y , fa [y] = x ;
zt( y ) , zt( x ) ;
}
inline void splay( int x , int pos ){
while( fa [x] != pos ){
R y = fa [x] , z = fa [y] ;
if( z != pos ) sk( x ) ^ sk( y ) ? spinup( x ) : spinup( y ) ;
spinup( x ) ;
} if( !pos ) root = x ;
}
inline void ins( int dlt ){
R now = root , fh = 0 ;
while( now && val [now] != dlt ) fh = now , now = tr( now , dlt ) ;
if( now ) size [now] ++ ;
else{
now = ++ znt ;
if( fh ) tr( fh , dlt ) = now ;
fa [now] = fh , val [now] = dlt ;
son [now] = size [now] = 1 ;
} splay( now , 0 ) ;
}
inline void find( int dlt ){
R now = root ;
while( tr( now , dlt ) && val [now] != dlt ) now = tr( now , dlt ) ;
splay( now , 0 ) ;
}
inline int ngr( int dlt , bool fg ){
find( dlt ) ; R now = root ;
if( val [now] != dlt && ( fg ^ ( dlt > val [now] ) ) ) return splay( now , 0 ) , now ;
now = ch [now][fg] ;
while( ch [now][fg ^ 1] ) now = ch [now][fg ^ 1] ;
return splay( now , 0 ) , now ;
}
inline void del( int dlt ){
int pre = ngr( dlt , 0 ) , nxt = ngr( dlt , 1 ) ;
splay( pre , 0 ) , splay( nxt , pre ) ;
if( size [ch [nxt][0]] > 1 ) size [ch [nxt][0]] -- , splay( ch [nxt][0] , 0 ) ;
else ch [nxt][0] = 0 , splay( nxt , 0 ) ;
}
inline int ranks( int dlt ){
find( dlt ) ;
R now = root ;
if( val [now] < dlt ) now = ngr( val [now] , 1 ) ;
return son [ch [now][0]] ;
}
inline int rk( int rank ){
R now = root ;
while( 1 ){
R nxt = ch [now][0] ;
if( size [now] + son [nxt] < rank ) rank -= ( size [now] + son [nxt] ) , now = ch [now][1] ;
else if( son [nxt] >= rank ) now = nxt ;
else return splay( now , 0 ) , now ;
}
}
void sc(){
n = read() , m = read() ;
for( R i = 1 ; i <= n ; i ++ ) ins( read() ) ;
}
void work(){
ins( Inf ) , ins( -Inf ) ;
while( m -- ){
opt = read() , x = read() ^ last ;
// printf( "%ld %ld\n" , opt , x ) ;
if( opt == 1 ) ins( x ) ;
else if( opt == 2 ) del( x ) ;
else if( opt == 3 ) ans ^= ( last = ranks( x ) ) ;
else if( opt == 4 ) ans ^= ( last = val [rk( x + 1 )] ) ;
else if( opt == 5 ) ans ^= ( last = val [ngr( x , 0 )] ) ;
else if( opt == 6 ) ans ^= ( last = val [ngr( x , 1 )] ) ;
} printf( "%ld\n" , ans ) ;
}
signed main(){
sc() ;
work() ;
return 0 ;
}
由于这个东西只能写一颗,所以我把它搞到结构体里面了,这样他不好看了,但是好用了。
只需要在所有的东西前面加一个splay.就可以了
code 2.0版
#include <cstring>
#include <algorithm>
#include <cstdio>
#define mp make_pair
#define R register int
#define int long
#define printf Ruusupuu = printf
int Ruusupuu ;
using namespace std ;
typedef long long L ;
typedef long double D ;
typedef unsigned long long G ;
typedef pair< int , int > PI ;
const int N = 1e5 + 10 ;
const int Inf = 0x3f3f3f3f ;
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch ^ '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , opt ;
struct Splay{
int root , znt , ch [N][2] , fa [N] , son [N] , val [N] , size [N] ;
#define zt( x ) son [x] = ( son [ch [x][0]] + son [ch [x][1]] + size [x] )
#define sk( x ) ( x == ch [fa [x]][1] )
#define tr( x , dlt ) ch [x][dlt > val [x]]
inline void spinup( int x ){
R y = fa [x] , z = fa [y] , k = sk( x ) ;
ch [z][sk(y)] = x , fa [x] = z ;
ch [y][k] = ch [x][k ^ 1] , fa [ch [x][k ^ 1]] = y ;
ch [x][k ^ 1] = y , fa [y] = x ;
zt( y ) , zt( x ) ;
}
inline void splay( int x , int pos ){
while( fa [x] != pos ){
R y = fa [x] ; R z = fa [y] ;
if( z != pos ) sk( x ) ^ sk ( y ) ? spinup( x ) : spinup( y ) ; //on the same line ? spinup( y ) : spinup( x ) ;
spinup( x ) ;
} if( !pos ) root = x ;
}
inline void ins( int dlt ){
R now = root , fh = 0 ;
while( now && val [now] != dlt ) fh = now , now = tr( now , dlt ) ;
if( now ) size [now] ++ ;
else {
now = ++ znt ;
if( fh ) tr( fh , dlt ) = now ;
size [now] = son [now] = 1 ;
fa [now] = fh , val [now] = dlt ;
}
splay( now , 0 ) ;
}
inline void find( int dlt ){
R now = root ; if( !now ) return ;
while( tr( now , dlt ) && val [now] != dlt )
now = tr( now , dlt ) ;
splay( now , 0 ) ;
}
inline int ngr( int dlt , bool fg ){
find( dlt ) ; R now = root ;
if( val [now] != dlt && ( fg ^ ( val [now] < dlt ) ) ) return now ;
now = ch [now][fg] ;
while( ch [now][fg ^ 1] ) now = ch [now][fg ^ 1] ;
return now ;
}
inline void del( int dlt ){
int pre = ngr( dlt , 0 ) , nxt = ngr( dlt , 1 ) ;
splay( pre , 0 ) , splay( nxt , pre ) ;
int now = ch [nxt][0] ;
if( size [now] > 1 ) size [now] -- , splay( now , 0 ) ;
else ch [nxt][0] = 0 ;
}
inline int rk( int rank ){
int now = root ;
if( son [now] < rank ) return 0 ;
while( 1 ){
int nxt = ch [now][0] ;
if( size [now] + son [nxt] < rank ) rank -= ( size [now] + son [nxt] ) , now = ch [now][1] ;
else if( son [nxt] >= rank ) now = nxt ;
else return val [now] ;
}
}
}splay ;
void sc(){
n = read() ;
}
void work(){
splay.ins( -Inf ) , splay.ins( Inf ) ;
while( n -- ){
opt = read() ;
if( opt == 1 ) splay.ins( read() ) ;
else if( opt == 2 ) splay.del( read() ) ;
else if( opt == 3 ) splay.find( read() ) , printf( "%ld\n" , splay.son [splay.ch [splay.root][0]] ) ;
else if( opt == 4 ) printf( "%ld\n" , splay.rk( read() + 1 ) ) ;
else if( opt == 5 ) printf( "%ld\n" , splay.val [splay.ngr( read() , 0 )] ) ;
else if( opt == 6 ) printf( "%ld\n" , splay.val [splay.ngr( read() , 1 )] ) ;
}
}
signed main(){
sc() ;
work() ;
return 0 ;
}
应\(\mathtt {zbw}\)要求,更新一个区间提取(分裂),但是话说,这不是区间操作吗?
先贴一个区间问题入门,建议先阅读再接着看,我的博客\(splay\)区间入门:文艺平衡树和火星人
\(splay\)区间处理主要靠的是标记,和线段树中的标记一样,查询的时候并不需要全部下传。
这也就意味着,如果我们存储一个关于的答案的值域的话,传标记的时候要一并把答案域更新。
每次\(splay\)之前,最好把所有标记全部下传。
这只需要在\(splay\)前面加一句话,写一个函数。
void spall( int x ){ if( fa [x] != root && fa [x] != 0 ) spall( fa [x] ) ; sp( x ) ; }
inline void splay( int x , int pos ){
spall( x ) ;
while( fa [x] != pos ){
R y = fa [x] , z = fa [y] ;
if( z != pos ) sk( x ) ^ sk( y ) ? spinup( x ) : spinup( y ) ;
spinup( x ) ;
} if( !pos ) root = x ;
}
注意\(spall\)这个函数实在回溯的时候下传标记的,保证了标记从根传到底。
小结一下:\(splay\)标记有关注意
- 每次下传标记都要保证子节点信息域和答案域均正确
- 每次有从上到下的遍历的时候必须下传标记
- \(splay\)之前最好下传标记
\(splay\)提取一个区间,我们可以把这个区间转出来,然后把他从树上割下来(把\(ch[fa[x][...]]\)设置成\(0\))
具体进阶推荐看这两篇提接以加深理解。
最长上升子序列,星际旅行
二逼平衡树先咕一下...
upd 2021.7.25
二逼平衡树更新啦,我自己的写法好像和众多写法不太一样,并且非常慢,非常费空间。
我是真的给每个节点都开一个\(splay\)。
所以空间需要开动态的。
删除需要回收空间。
但是写起来很方便。
操作一就是在每个区间找有多少个比他小的数。
操作二二分答案变操作一。
操作三先删后加。
操作四,操作五都是对小于/大于他的取\(min,max\)就行了。
code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define R register int
#define scanf Ruusupuu = scanf
#define printf Ruusupuu = printf
#define freopen rsp_5u = freopen
int Ruusupuu ;
FILE * rsp_5u ;
using namespace std ;
typedef long long L ;
typedef double D ;
const int N = 5e4 + 10 ;
const int Inf = 2147483647 ;
inline void of(){ freopen( "in.in" , "r" , stdin ) , freopen( "out.out" , "w" , stdout ) ; }
inline void cf(){ fclose( stdin ) , fclose( stdout ) ; }
inline int read(){
int w = 0 ; bool fg = 0 ; char ch = getchar() ;
while( ch < '0' || ch > '9' ) fg |= ( ch == '-' ) , ch = getchar() ;
while( ch >= '0' && ch <= '9' ) w = ( w << 1 ) + ( w << 3 ) + ( ch - '0' ) , ch = getchar() ;
return fg ? -w : w ;
}
int n , m , opt ;
struct Splay{
int root , znt , *fa , **ch , *son , *size , *val , *pool , top ;
inline void Size( int x ){
fa = new int [x] ;
son = new int [x] ;
size = new int [x] ;
val = new int [x] ;
ch = new int *[x] ;
pool = new int [x] ;
for( R i = 0 ; i < x ; i ++ ) ch [i] = new int [2] ;
}
#define zt( x ) son [x] = son [ch [x][0]] + son [ch [x][1]] + size [x]
#define sk( x ) ( x == ch [fa [x]][1] )
#define tr( x , dlt ) ch [x][dlt > val [x]]
inline void spinup( int x ){
R y = fa [x] , z = fa [y] , k = sk( x ) ;
ch [z][sk(y)] = x , fa [x] = z ;
ch [y][k] = ch [x][k ^ 1] , fa [ch [x][k ^ 1]] = y ;
ch [x][k ^ 1] = y , fa [y] = x ;
zt( y ) , zt( x ) ;
}
inline void splay( int x , int pos ){
while( fa [x] != pos ){
R y = fa [x] , z = fa [y] ;
if( z != pos ) sk( x ) ^ sk( y ) ? spinup( x ) : spinup( y ) ;
spinup( x ) ;
} if( !pos ) root = x ;
}
inline void ins( int dlt ){
R now = root , fh = 0 ;
while( now && val [now] != dlt ) fh = now , now = tr( now , dlt ) ;
if( now ) size [now] ++ ;
else{
now = ( top ) ? ( pool [top --] ) : ( ++ znt ) ;
if( fh ) tr( fh , dlt ) = now ;
fa [now] = fh , val [now] = dlt ;
son [now] = size [now] = 1 ;
} splay( now , 0 ) ;
}
inline void find( int dlt ){
R now = root ;
while( tr( now , dlt ) && val [now] != dlt ) now = tr( now , dlt ) ;
splay( now , 0 ) ;
}
inline int ngr( int dlt , bool fg ){
find( dlt ) ; R now = root ;
if( val [now] != dlt && ( fg ^ ( dlt > val [now] ) ) ) return splay( now , 0 ) , now ;
now = ch [now][fg] ;
while( ch [now][fg ^ 1] ) now = ch [now][fg ^ 1] ;
return splay( now , 0 ) , now ;
}
inline void del( int dlt ){
R pre = ngr( dlt , 0 ) , nxt = ngr( dlt , 1 ) ;
splay( pre , 0 ) , splay( nxt , pre ) ;
if( size [ch [nxt][0]] > 1 ) size [ch [nxt][0]] -- , splay( ch [nxt][0] , 0 ) ;
else pool [++ top] = ch [nxt][0] , ch [nxt][0] = 0 , splay( nxt , 0 ) ;
}
inline int rk( int rank ){
R now = root ;
while( 1 ){
R nxt = ch [now][0] ;
if( son [nxt] + size [now] < rank ) rank -= ( son [nxt] + size [now] ) , now = ch [now][1] ;
else if( son [nxt] >= rank ) now = nxt ;
else return splay( now , 0 ) , now ;
}
}
inline int ranks( int dlt ){
find( dlt ) ;
R now = root ;
if( val [now] < dlt ) now = ngr( val [now] , 1 ) ;
return son [ch [now][0]] - 1 ;
}
inline int rks( int dlt ){
find( dlt ) ;
R now = root ;
if( val [now] < dlt ) now = ngr( val [now] , 1 ) ;
return son [ch [now][0]] - 1 + ( ( val [now] == dlt ) ? size [now] : 0 ) ;
}
} ;
struct Ts{ int l , r ; Splay data ; } t [N << 2] ;
int lx , rx , pos , dlt , plt ;
void buid( int x , int l , int r ){
t [x].l = l , t [x].r = r ;
t [x].data.Size( r - l + 4 ) ;
// printf( "ASKSPACE%d %d %d %d\n" , x , l , r , r - l + 4 ) ;
t [x].data.ins( -Inf ) , t [x].data.ins( Inf ) ;
if( l == r ) return ;
int mid = ( l + r ) >> 1 ;
buid( x << 1 , l , mid ) ;
buid( x << 1 | 1 , mid + 1 , r ) ;
}
void ins( int x ){
t [x].data.ins( dlt ) ;
// printf( "USING%d %d %d\n" , t [x].l , t [x].r , x ) ;
if( t [x].l == t [x].r ) return ;
int mid = ( t [x].l + t [x].r ) >> 1 ;
if( pos <= mid ) ins( x << 1 ) ;
else ins( x << 1 | 1 ) ;
}
void del( int x ){
t [x].data.del( dlt ) ;
if( t [x].l == t [x].r ) return ;
int mid = ( t [x].l + t [x].r ) >> 1 ;
if( pos <= mid ) del( x << 1 ) ;
else del( x << 1 | 1 ) ;
}
int askone( int x ){
if( t [x].l == t [x].r ) return t [x].data.val [t [x].data.rk( 2 )] ;
int mid = ( t [x].l + t [x].r ) >> 1 ;
if( pos <= mid ) return askone( x << 1 ) ;
else return askone( x << 1 | 1 ) ;
}
inline void upd(){
dlt = askone( 1 ) , del( 1 ) ;
dlt = read() , ins( 1 ) ;
}
int Askrank( int x ){
if( t [x].l >= lx && t [x].r <= rx ) return t [x].data.ranks( dlt ) ;
int mid = ( t [x].l + t [x].r ) >> 1 , ans = 0 ;
if( lx <= mid ) ans += Askrank( x << 1 ) ;
if( rx > mid ) ans += Askrank( x << 1 | 1 ) ;
return ans ;
}
inline int Boundans(){
// puts( "BOUND" ) ;
int lside = 0 , rside = 1e8 + 10 , ans = 0 ;
while( lside <= rside ){
dlt = ( lside + rside ) >> 1 ;
// printf( "%d %d %d\n" , dlt , plt , Askrank( 1 ) ) ;
if( Askrank( 1 ) <= plt ) ans = dlt , lside = dlt + 1 ;
else rside = dlt - 1 ;
} return ans ;
}
int Askpre( int x ){
if( t [x].l >= lx && t [x].r <= rx ) return t [x].data.val [t [x].data.ngr( dlt , 0 )] ;
int mid = ( t [x].l + t [x].r ) >> 1 , ans = -Inf ;
if( lx <= mid ) ans = max( ans , Askpre( x << 1 ) ) ;
if( rx > mid ) ans = max( ans , Askpre( x << 1 | 1 ) ) ;
return ans ;
}
int Asknxt( int x ){
if( t [x].l >= lx && t [x].r <= rx ) return t [x].data.val [t [x].data.ngr( dlt , 1 )] ;
int mid = ( t [x].l + t [x].r ) >> 1 , ans = Inf ;
if( lx <= mid ) ans = min( ans , Asknxt( x << 1 ) ) ;
if( rx > mid ) ans = min( ans , Asknxt( x << 1 | 1 ) ) ;
return ans ;
}
void sc(){
n = read() , m = read() ;
buid( 1 , 1 , n ) ;
for( R i = 1 ; i <= n ; i ++ ) pos = i , dlt = read() , ins( 1 ) ;
}
void work(){
while( m -- ){
opt = read() ;
if( opt == 1 ) lx = read() , rx = read() , dlt = read() , printf( "%d\n" , Askrank( 1 ) + 1 ) ;
else if( opt == 2 ) lx = read() , rx = read() , plt = read() - 1 , printf( "%d\n" , Boundans() ) ;
else if( opt == 3 ) pos = read() , upd() ;
else if( opt == 4 ) lx = read() , rx = read() , dlt = read() , printf( "%d\n" , Askpre( 1 ) ) ;
else if( opt == 5 ) lx = read() , rx = read() , dlt = read() , printf( "%d\n" , Asknxt( 1 ) ) ;
}
}
signed main(){
sc() ;
work() ;
return 0 ;
}

浙公网安备 33010602011771号