AC_CSP @ 2023-03-03 17:55:55
# include <bits/stdc++.h>
using namespace std ;
const int N = 1e5 + 7 ;
const int INF = 0x3f3f3f3f ;
int rt , ch[N][2] , fa[N] , val[N] , cnt[N] , size[N] , tot , tag[N] ;
inline void upd_size ( int u ) { size[u] = cnt[u] + size[ch[u][0]] + size[ch[u][1]] ; }
inline bool get ( int u ) { return u == ch[fa[u]][1] ; }
inline void push_down ( int u ) {
if ( u && tag[u] ) {
tag[ch[u][0]] ^= 1 ;
tag[ch[u][1]] ^= 1 ;
swap ( ch[u][0] , ch[u][1] ) ;
tag[u] = 0 ;
}
}
inline void _rotate ( int x ) {
int y = fa[x] , z = fa[y] , opt = get ( x ) ;
push_down ( x ) , push_down ( y ) ;
ch[y][opt] = ch[x][opt ^ 1] ;
if ( ch[x][opt ^ 1] ) fa[ch[x][opt ^ 1]] = y ;
ch[x][opt ^ 1] = y ; fa[y] = x ; fa[x] = z ;
if ( z ) ch[z][ get ( y ) ] = x;
upd_size ( y ) , upd_size ( x ) ;
}
inline void Splay ( int x , int to ) {
for ( int f = fa[x] ; f = fa[x] , f != to ; _rotate ( x ) )
if ( fa[f] != to ) _rotate ( get ( x ) == get ( f ) ? f : x ) ;
// cout << "Error : " << x << "\n" ;
if ( to == 0 ) rt = x ;
}
inline int find ( int x ) {
int now = rt ;
// cout << "begin :: find \n" ;
while ( 1 ) {
// cout << size[0] << " !!! \n" ;
// cout << "Error _ now / x : " << now << " " << x << "\n" ;
// cout << "Ch : " << ch[now][0] << " " << ch[now][1] << "\n" ;
// cout << "Size : " << size[ch[now][0]] << "\n" ;
push_down(now) ;
if ( x <= size[ch[now][0]] ) now = ch[now][0] ;
else{
x -= size[ch[now][0]] + 1 ;
if ( !x ) return now ;
// cout << "enter right\n" ;
now = ch[now][1] ;
}
}
}
inline void reverse ( int x , int y ) {
int l = x - 1 , r = y + 1 ;
l = find ( l ) , r = find ( r ) ;
Splay ( l , 0 ) , Splay ( r , l ) ;
tag[ch[ch[rt][1]][0]] ^= 1 ;
}
inline void dfs ( int u ) {
// cout << u << "\n" ;
push_down(u) ;
if ( ch[u][0] ) dfs ( ch[u][0] ) ;
if ( val[u] != INF && val[u] != -INF ) cout << val[u] << " " ;
if ( ch[u][1] ) dfs ( ch[u][1] ) ;
}
inline void insert ( int x ) {
if ( !rt ) {
rt = ++ tot ; val[tot] = x ; cnt[tot] = 1 ; size[tot] = 1 ;
return ;
}
int now = rt , f = 0 ;
while ( 1 ) {
// cout << f << " " << now << "\n" ;
f = now , now = ch[now][val[ch[now][0]] < x] ;
// cout << "Error1\n" ;
if ( !now ) {
val[++tot] = x , cnt[tot] = 1 , size[tot] = 1 , fa[tot] = f , ch[f][val[f] < x] = now ;
// cout << "Error2\n" ;
// cout << cnt[1] << " " << size[1] << " " << ch[1][0] << " " << ch[1][1] << "\n" ;
upd_size ( f ) ;
// cout << "Error4\n" ;
Splay ( tot , 0 ) ; break ;
}
}
}
int main () {
int n , m ;
// ios :: sync_with_stdio(false) ; cin . tie(0) , cout . tie(0) ;
cin >> n >> m ;
// cout << "here\n" ;
insert ( INF ) , insert ( - INF ) ; // cout << "Error3\n" ;
for ( int i = 1 ; i <= n ; i++ ) insert(i) ;
// cout << "ereh\n" ;
while ( m-- ) {
// cout << size[0] << " 草 \n" ;
int x , y ;
cin >> x >> y ;
reverse ( x + 1 , y + 1 ) ;
}
cout << rt ;
dfs ( rt ) ;
return 0 ;
}
by 2018ljw @ 2023-03-03 18:35:31
@AC_CSP
稍微用自己码风改写了一下,fx
就是 get
函数
void rotate(int x){
int y=fa[x],z=fa[y],p=fx(x);
pushdown(x);pushdown(y);
son[y][p]=son[x][p^1];
if(son[x][p^1])fa[son[x][p^1]]=y;
son[x][p^1]=y;
fa[y]=x;fa[x]=z;
if(z)son[z][fx(y)]=x;
pushup(y),pushup(x);
}
前面都写的很对,但到 if(z)son[z][fx(y)]=x;
这步时,y
的信息已经更新完了,fx(y)
得到的已经不是原先 y
是 z
的哪个儿子了。
把这句话提到 pushdown
下面即可。
by AC_CSP @ 2023-03-03 21:25:23
@2018ljw 感谢!顺便问个小问题,为什么先下放儿子再下放父亲,我怎么感觉先下放父亲才准确(
by AC_CSP @ 2023-03-03 21:25:52
@2018ljw 已经关注的人就不能关注第二次了qwq
by 2018ljw @ 2023-03-03 21:35:48
@AC_CSP
感觉都可以吧,正常来说 rotate x 的时候因为是从根出发的所以父亲应该已经访问过没有标记了
by AC_CSP @ 2023-03-03 21:48:15
@2018ljw 谢谢,明白了qwq