last update :2023/10/13
模板综合
卡常
1.快读
inline int read ( ) {
int s= 0 , m= 0 ; char ch= getchar ( ) ;
while ( ! isdigit ( ch) ) { if ( ch== '-' ) m= 1 ; ch= getchar ( ) ; }
while ( isdigit ( ch) ) s= ( s<< 3 ) + ( s<< 1 ) + ( ch^ 48 ) , ch= getchar ( ) ;
return m? - s: s;
}
2.快输
inline void write ( int x) {
if ( x< 0 ) putchar ( '-' ) , x= - x;
if ( x> 9 ) write ( x/ 10 ) ;
putchar ( x- x/ 10 * 10 + '0' ) ;
}
高精度
struct BIG {
int num[ ] , len;
BIG ( ) {
memset ( num, 0 , sizeof ( num) ) ;
len= 0 ;
}
BIG operator + ( const BIG & x) {
BIG ans; int u= 0 ;
ans. len= max ( len, x. len) ;
for ( int i= 1 ; i<= ans. len; i++ ) {
ans. num[ i] = ( num[ i] + x. num[ i] + u) % 10 ;
u= ( num[ i] + x. num[ i] + u) / 10 ;
}
if ( u!= 0 )
ans. num[ ++ ans. len] = u;
return ans;
}
BIG operator - ( const BIG & x) {
BIG ans; int u= 0 ;
ans. len= len;
for ( int i= 1 ; i<= ans. len; i++ ) {
ans. num[ i] = ( num[ i] - x. num[ i] - u+ 10 ) % 10 ;
u= ( num[ i] - u< x. num[ i] ) ;
}
while ( ans. num[ ans. len] == 0 && ans. len> 1 )
ans. len-- ;
return ans;
}
BIG operator * ( const BIG & x) {
BIG ans; int u= 0 ;
ans. len= len+ x. len- 1 ;
for ( int i= 1 ; i<= len; i++ )
for ( int j= 1 ; j<= x. len; j++ )
ans. num[ i+ j- 1 ] += num[ i] * x. num[ j] ;
for ( int i= 1 ; i<= ans. len; i++ ) {
ans. num[ i] = ans. num[ i] + u;
u= ans. num[ i] / 10 , ans. num[ i] %= 10 ;
}
for ( ; u; u/= 10 )
ans. num[ ++ ans. len] = u% 10 ;
return ans;
}
BIG operator / ( const int & x) {
BIG ans; int u= 0 ;
ans. len= len;
for ( int i= ans. len; i; i-- ) {
ans. num[ i] = ( u* 10 + num[ i] ) / x;
u= ( u* 10 + num[ i] ) % x;
}
while ( ans. num[ ans. len] == 0 && ans. len> 1 )
ans. len-- ;
return ans;
}
int operator % ( const int & x) {
int u= 0 ;
for ( int i= len; i; i-- )
u= ( u* 10 + num[ i] ) % x;
return u;
}
} ;
BIG int_big ( int a) {
BIG ans;
for ( int i= a; i; i/= 10 )
ans. num[ ++ ans. len] = a% 10 ;
return ans;
}
BIG str_big ( string s) {
BIG ans;
for ( int i= s. size ( ) - 1 ; i>= 0 ; i-- )
ans. num[ ++ ans. len] = s[ i] - '0' ;
return ans;
}
string big_str ( BIG a) {
string s= "" ;
for ( int i= 1 ; i<= a. len; i++ )
s= s+ char ( a. num[ i] + '0' ) ;
return s;
}
BIG read ( ) {
string s;
cin>> s;
return str_big ( s) ;
}
void print ( BIG a) {
for ( int i= a. len; i; i-- )
cout<< a. num[ i] ;
putchar ( '\n' ) ;
}
字符串
1.KMP匹配
int nxt[ ] ;
void get ( char t[ ] ) {
nxt[ 1 ] = 0 ;
for ( int i= 2 , j= 0 ; i<= strlen ( t+ 1 ) ; i++ ) {
while ( j&& t[ i] != t[ j+ 1 ] )
j= nxt[ j] ;
if ( t[ i] == t[ j+ 1 ] )
j++ ;
nxt[ i] = j;
}
}
int kmp ( char s[ ] , char t[ ] ) {
get ( t) ;
for ( int i= 1 , j= 0 ; i<= strlen ( s+ 1 ) ; i++ ) {
while ( j&& s[ i] != t[ j+ 1 ] )
j= nxt[ j] ;
if ( s[ i] == t[ j+ 1 ] )
j++ ;
if ( j== strlen ( t+ 1 ) )
return i- j+ 1 ;
}
return - 1 ;
}
2.Manacher
char str[ ] , tmp[ ] ;
int p[ ] ;
char * add ( char * s) {
int cnt= 0 , l= strlen ( s) ;
tmp[ 0 ] = '(' , tmp[ ++ cnt] = '$' ;
for ( int i= 0 ; i< l; i++ )
tmp[ ++ cnt] = s[ i] , tmp[ ++ cnt] = '$' ;
tmp[ ++ cnt] = ')' ;
return tmp;
}
int manacher ( char * s) {
int ans= 0 , r= 0 , mid= 0 , l= strlen ( s) ;
for ( int i= 1 ; i< l- 1 ; i++ ) {
p[ i] = ( r>= i? min ( p[ 2 * mid- i] , r- i) : 1 ) ;
while ( s[ i+ p[ i] ] == s[ i- p[ i] ] )
p[ i] ++ ;
if ( i+ p[ i] > r)
r= i+ p[ i] , mid= i;
ans= max ( ans, p[ i] ) ;
}
return ans- 1 ;
}
3.后缀数组
int n, m, sa[ ] , rk[ ] , height[ ] , t[ ] ;
int x[ ] , y[ ] ;
void get_sa ( char s[ ] ) {
n= strlen ( s+ 1 ) , m= 266 ;
for ( int i= 1 ; i<= n; i++ ) t[ x[ i] = s[ i] ] ++ ;
for ( int i= 2 ; i<= m; i++ ) t[ i] += t[ i- 1 ] ;
for ( int i= n; i; i-- ) sa[ t[ x[ i] ] -- ] = i;
for ( int k= 1 , cnt= 0 ; k<= n; k*= 2 ) {
cnt= 0 ;
for ( int i= n- k+ 1 ; i<= n; i++ ) y[ ++ cnt] = i;
for ( int i= 1 ; i<= n; i++ ) if ( sa[ i] > k) y[ ++ cnt] = sa[ i] - k;
memset ( t, 0 , sizeof ( t) ) ;
for ( int i= 1 ; i<= n; i++ ) t[ x[ i] ] ++ ;
for ( int i= 2 ; i<= m; i++ ) t[ i] += t[ i- 1 ] ;
for ( int i= n; i; i-- ) sa[ t[ x[ y[ i] ] ] -- ] = y[ i] , y[ i] = 0 ;
swap ( x, y) ; x[ sa[ 1 ] ] = cnt= 1 ;
for ( int i= 2 ; i<= n; i++ )
cnt+= ( y[ sa[ i] ] != y[ sa[ i- 1 ] ] || y[ sa[ i] + k] != y[ sa[ i- 1 ] + k] ) , x[ sa[ i] ] = cnt;
if ( cnt== n) break ;
m= cnt;
}
for ( int i= 1 ; i<= n; i++ ) rk[ sa[ i] ] = i;
for ( int i= 1 , k= 0 ; i<= n; i++ ) {
if ( rk[ i] == 1 ) continue ;
k= max ( 0 , k- 1 ) ; int j= sa[ rk[ i] - 1 ] ;
while ( i+ k<= n&& j+ k<= n&& s[ i+ k] == s[ j+ k] ) k++ ;
height[ rk[ i] ] = k;
}
}
数论
1.(拓展)欧几里得算法
int exgcd ( int a, int b, int & x, int & y) {
if ( ! b) { x= 1 , y= 0 ; return a; }
int d= exgcd ( b, a% b, y, x) ;
y= y- a/ b* x;
return d;
}
2.快速乘
int qmul ( int x, int y, int mod) {
int s= 0 ;
while ( y) {
if ( y& 1 ) s= ( s+ x) % mod;
x= x* 2 % mod, y>>= 1 ;
}
return s;
}
3.快速幂
int qpow ( int x, int y, int mod= M) {
int s= 1 ;
while ( y) {
if ( y& 1 ) s= ( s* x) % mod;
x= x* x% mod, y>>= 1 ;
}
return s;
}
4.(拓展)中国剩余定理
int n, a, b, a0, b0;
void merge ( int a1, int b1, int a2, int b2) {
int x, y;
int d= exgcd ( a1, a2, x, y) ;
x= x* ( ( b2- b1) / d) % ( a2/ d) ;
if ( x< 0 ) x+= a2/ d;
a= a1/ d* a2;
b= ( a1* x+ b1) % a;
if ( b< 0 ) b+= a;
}
5.欧拉函数
直接求解
int phi ( int n) {
int ans= n;
for ( int i= 2 ; i* i<= n; i++ ) if ( n% i== 0 ) {
ans= ans/ i* ( i- 1 ) ;
while ( n% i== 0 ) n/= i;
}
if ( n> 1 ) ans= ans/ n* ( n- 1 ) ;
return ans;
}
预处理(即线性筛)
int p[ ] , phi[ ] , v[ ] , cnt;
void init ( int n) {
phi[ 1 ] = 1 ;
for ( int i= 2 ; i<= n; i++ ) {
if ( ! v[ i] ) p[ ++ cnt] = i, phi[ i] = i- 1 ;
for ( int j= 1 ; j<= cnt&& i* p[ j] <= n; j++ ) {
v[ i* p[ j] ] = 1 ;
if ( i% p[ j] == 0 ) {
phi[ i* p[ j] ] = phi[ i] * p[ j] ;
break ;
}
else phi[ i* p[ j] ] = phi[ i] * phi[ p[ j] ] ;
}
}
}
6.FFT
int rv[ ] ;
void init ( int k) {
for ( int i= 0 ; i< ( 1 << k) ; i++ )
rv[ i] = ( rv[ i>> 1 ] >> 1 ) | ( ( i& 1 ) << ( k- 1 ) ) ;
}
# define cp complex< double >
void fft ( cp a[ ] , int n, int fl) {
for ( int i= 0 ; i< n; i++ )
if ( i< rv[ i] ) swap ( a[ i] , a[ rv[ i] ] ) ;
for ( int i= 1 ; i< n; i*= 2 ) {
cp wi= exp ( cp ( 0 , fl* pi/ i) ) ;
for ( int j= 0 ; j< n; j+= i* 2 ) {
cp w ( 1 , 0 ) ;
for ( int k= j; k< i+ j; k++ , w*= wi) {
cp x= a[ k] , y= w* a[ k+ i] ;
a[ k] = x+ y, a[ k+ i] = x- y;
}
}
}
if ( fl== - 1 ) for ( int i= 0 ; i< n; i++ ) a[ i] /= n;
}
7.NTT
int rv[ ] ;
void init ( int k) {
for ( int i= 0 ; i< ( 1 << k) ; i++ )
rv[ i] = ( rv[ i>> 1 ] >> 1 ) | ( ( i& 1 ) << ( k- 1 ) ) ;
}
void ntt ( int a[ ] , int n, int fl) {
for ( int i= 0 ; i< n; i++ )
if ( i< rv[ i] ) swap ( a[ i] , a[ rv[ i] ] ) ;
int ginv= qpow ( gt, M- 2 ) ;
for ( int i= 1 ; i< n; i*= 2 ) {
int gi= qpow ( ( fl== 1 ? gt: ginv) , ( M- 1 ) / i/ 2 ) ;
for ( int j= 0 ; j< n; j+= i* 2 ) {
int g= 1 ;
for ( int k= j, g= 1 ; k< i+ j; k++ , g= g* gi% M) {
int x= a[ k] , y= g* a[ k+ i] % M;
a[ k] = ( x+ y) % M, a[ k+ i] = ( x- y+ M) % M;
}
}
}
int ninv= qpow ( n, M- 2 ) ;
if ( fl== - 1 ) for ( int i= 0 ; i< n; i++ ) a[ i] = a[ i] * ninv% M;
}
图论
结构体式链式前向星
int h[ ] , cnt;
struct QWQ { int v, w, nxt; } e[ * 2 ] ;
void add ( int u, int v, int w) { e[ ++ cnt] = { v, w, h[ u] } , h[ u] = cnt; }
最短路
1.SPFA
int d[ ] , vis[ ] ;
queue< int > q;
void SPFA ( int start) {
while ( q. size ( ) ) q. pop ( ) ;
memset ( d, 0x3f , sizeof ( d) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
d[ start] = 0 , vis[ start] = 1 , q. push ( start) ;
while ( q. size ( ) ) {
int u= q. front ( ) ; q. pop ( ) ;
vis[ u] = 0 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( d[ v] > d[ u] + w) {
if ( ! vis[ v] ) q. push ( v) , vis[ v] = 1 ;
d[ v] = d[ u] + w;
}
}
}
}
2.dijkstra
int d[ ] , vis[ ] ;
struct Node {
int to, len;
bool operator < ( const Node& x) const { return len> x. len; }
} ;
priority_queue< Node> pq;
void dijkstra ( int start) {
while ( pq. size ( ) ) pq. pop ( ) ;
memset ( d, 0x3f , sizeof ( d) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
d[ start] = 0 , pq. push ( { start, 0 } ) ;
while ( pq. size ( ) ) {
int u= pq. top ( ) . to; pq. pop ( ) ;
if ( vis[ u] ) continue ;
vis[ u] = 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( d[ v] > d[ u] + w) {
d[ v] = d[ u] + w;
if ( ! vis[ v] ) pq. push ( { v, d[ v] } ) ;
}
}
}
}
3.floyd
拓扑序
int in[ ] ;
queue< int > q;
void topo ( ) {
while ( ! q. empty ( ) ) {
int u= q. front ( ) ;
q. pop ( ) ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
in[ v] -- ;
if ( in[ v] == 0 ) q. push ( v) ;
}
}
}
最小生成树
1.kruskal
int f[ ] ;
struct qwq { int u, v, w; } e1[ ] ;
bool cmp ( qwq& x, qwq& y) { return x. w< y. w; }
void init ( int n) { for ( int i= 1 ; i<= n; i++ ) f[ i] = i; }
int find ( int x) { return ( f[ x] == x? x: f[ x] = find ( f[ x] ) ) ; }
void merge ( int x, int y) { f[ find ( x) ] = find ( y) ; }
void kruskal ( ) {
init ( n) ;
sort ( e1+ 1 , e1+ m+ 1 , cmp) ;
for ( int i= 1 ; i<= m; i++ ) {
int u= e1[ i] . u, v= e1[ i] . v, w= e1[ i] . w;
if ( find ( u) != find ( v) )
merge ( u, v) ;
}
}
2.prim
bool vis[ ] ;
int d[ ] ;
void prim ( ) {
memset ( d, 0x3f , sizeof ( d) ) ;
d[ 1 ] = 0 ;
for ( int k= 1 ; k<= n; k++ ) {
int u= 0 , minn= 1e9 ;
for ( int i= 1 ; i<= n; i++ )
if ( vis[ i] == 0 && d[ i] < minn)
u= i, minn= d[ i] ;
vis[ u] = 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( vis[ v] == 0 )
d[ v] = min ( d[ v] , w) ;
}
}
}
tarjan
stack< int > st;
int f[ ] , dfn[ ] , low[ ] , cnt, k, scc[ ] ;
void tarjan ( int u, int fa) {
st. push ( u) ;
f[ u] = 1 , dfn[ u] = low[ u] = ++ cnt;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( ! dfn[ v] ) {
tarjan ( v, u) , low[ u] = min ( low[ u] , low[ v] ) ;
if ( ( u== fa&& num> 1 ) || ( u!= fa&& dfn[ u] <= low[ v] ) )
if ( dfn[ u] < low[ v] )
}
else if ( f[ v] )
low[ u] = min ( low[ u] , dfn[ v] ) ;
}
if ( dfn[ u] == low[ u] ) {
k++ ;
while ( 1 ) {
int top= st. top ( ) ; st. pop ( ) ;
scc[ top] = k, f[ top] = 0 ;
if ( top== u) break ;
}
}
}
树链剖分
int d[ ] , fa[ ] , sz[ ] , son[ ] , id[ ] , tot, top[ ] ;
void dfs1 ( int u, int p) {
fa[ u] = p, d[ u] = d[ p] + 1 , sz[ u] = 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( v== p) continue ;
dfs1 ( v, u) ; sz[ u] += sz[ v] ;
if ( sz[ v] >= sz[ son[ u] ] ) son[ u] = v;
}
}
void dfs2 ( int u, int tt) {
id[ u] = ++ tot, aa[ tot] = a[ u] , top[ u] = tt;
if ( ! son[ u] ) return ;
dfs2 ( son[ u] , tt) ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( v== fa[ u] || v== son[ u] ) continue ;
dfs2 ( v, v) ;
}
}
void jump ( int x, int y) {
while ( top[ x] != top[ y] ) {
if ( d[ top[ x] ] < d[ top[ y] ] ) swap ( x, y) ;
x= fa[ top[ x] ] ;
}
if ( d[ x] > d[ y] ) swap ( x, y) ;
}
LCA
1.倍增
int d[ ] , lg[ ] , fa[ ] [ 25 ] ;
void init ( int n) { for ( int i= 1 ; i<= n; i++ ) lg[ i] = lg[ i- 1 ] + ( 1 << lg[ i- 1 ] == i) ; }
void dfs ( int u, int p) {
d[ u] = d[ p] + 1 , fa[ u] [ 0 ] = p;
for ( int i= 1 ; ( 1 << i) <= d[ u] ; i++ ) fa[ u] [ i] = fa[ fa[ u] [ i- 1 ] ] [ i- 1 ] ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( v== p) continue ;
dfs ( v, u) ;
}
}
int lca ( int x, int y) {
if ( d[ x] < d[ y] ) swap ( x, y) ;
while ( d[ x] > d[ y] ) x= fa[ x] [ lg[ d[ x] - d[ y] ] - 1 ] ;
if ( x== y) return x;
for ( int k= lg[ d[ x] ] ; k>= 0 ; k-- ) if ( fa[ x] [ k] != fa[ y] [ k] ) x= fa[ x] [ k] , y= fa[ y] [ k] ;
return fa[ x] [ 0 ] ;
}
2.欧拉序
int d[ ] , st[ * 2 ] [ 25 ] , id[ ] , len;
void dfs ( int u, int p) {
d[ u] = d[ p] + 1 , id[ u] = ++ len, st[ len] [ 0 ] = u;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( ! id[ v] ) {
dfs ( v, u) ;
st[ ++ len] [ 0 ] = u;
}
}
}
void init ( ) {
for ( int j= 1 ; ( 1 << j) <= len; j++ )
for ( int i= 1 ; i+ ( 1 << j) - 1 <= len; i++ )
st[ i] [ j] = cmp ( st[ i] [ j- 1 ] , st[ i+ ( 1 << j- 1 ) ] [ j- 1 ] ) ;
}
int cmp ( int a, int b) { return d[ a] < d[ b] ? a: b; }
int query ( int l, int r) {
int k= log2 ( r- l+ 1 ) ;
return cmp ( st[ l] [ k] , st[ r- ( 1 << k) + 1 ] [ k] ) ;
}
int lca ( int x, int y) { return query ( min ( id[ x] , id[ y] ) , max ( id[ x] , id[ y] ) ) ; }
3.tarjan(离线)
int n, m, vis[ ] , f[ ] ;
map< pair< int , int > , int > ans;
vector< int > t[ ] ;
void init ( int n) { for ( int i= 1 ; i<= n; i++ ) f[ i] = i; }
int find ( int x) { return ( f[ x] == x? x: f[ x] = find ( f[ x] ) ) ; }
void merge ( int x, int y) { f[ find ( x) ] = find ( y) ; }
void tarjan ( int u) {
vis[ u] = 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
tarjan ( v) ; marge ( v, u) ;
}
for ( int i= 0 ; i< t[ u] . size ( ) ; i++ ) if ( vis[ y[ u] [ i] ] )
ans[ make_pair ( u, t[ u] [ i] ) ] = ans[ make_pair ( t[ u] [ i] , u) ] = find ( t[ u] [ i] ) ;
}
4.树链剖分
int d[ ] , fa[ ] , sz[ ] , son[ ] , id[ ] , tot, top[ ] ;
void dfs1 ( int u, int p) {
fa[ u] = p, d[ u] = d[ p] + 1 , sz[ u] = 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( v== p) continue ;
dfs1 ( v, u) ; sz[ u] += sz[ v] ;
if ( sz[ v] >= sz[ son[ u] ] ) son[ u] = v;
}
}
void dfs2 ( int u, int tt) {
id[ u] = ++ tot, top[ u] = tt;
if ( ! son[ u] ) return ;
dfs2 ( son[ u] , tt) ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( v== fa[ u] || v== son[ u] ) continue ;
dfs2 ( v, v) ;
}
}
int lca ( int x, int y) {
while ( top[ x] != top[ y] ) {
if ( d[ top[ x] ] < d[ top[ y] ] ) swap ( x, y) ;
x= fa[ top[ x] ] ;
}
if ( d[ x] > d[ y] ) swap ( x, y) ;
return x;
}
最大流
1.EK
最大流
int g[ ] [ ] ;
int flo[ ] , pre[ ] ;
queue< int > q;
int bfs ( int s, int t) {
while ( q. size ( ) ) q. pop ( ) ;
memset ( flo, 0 , sizeof ( flo) ) ;
memset ( pre, 0 , sizeof ( pre) ) ;
q. push ( s) , flo[ s] = INT_MAX;
while ( q. size ( ) ) {
int u= q. front ( ) ; q. pop ( ) ;
if ( u== t) return flo[ t] ;
for ( int v= 1 ; v<= n; v++ ) {
if ( ! g[ u] [ v] || pre[ v] ) continue ;
flo[ v] = min ( flo[ u] , g[ u] [ v] ) ;
q. push ( v) , pre[ v] = u;
}
}
return - 1 ;
}
int EK ( int s, int t) {
int p, maxflow= 0 ;
while ( ( p= bfs ( s, t) ) != - 1 ) {
for ( int i= t; i!= s; i= pre[ i] )
g[ pre[ i] ] [ i] -= p, g[ i] [ pre[ i] ] += p;
maxflow+= p;
}
return maxflow;
}
最小费用最大流
int flo[ ] , pre[ ] , dis[ ] , vis[ ] , l[ ] ;
queue< int > q;
int SPFA ( int s, int t) {
while ( q. size ( ) ) q. pop ( ) ;
memset ( flo, 0 , sizeof ( flo) ) ;
memset ( dis, 0x3f , sizeof ( dis) ) ;
memset ( vis, 0 , sizeof ( vis) ) ;
q. push ( s) , flo[ s] = INT_MAX, dis[ s] = 0 , vis[ s] = 1 ;
while ( q. size ( ) ) {
int u= q. front ( ) ; q. pop ( ) ;
vis[ u] = 0 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w, c= e[ i] . c;
if ( ! w|| dis[ v] <= dis[ u] + c) continue ;
if ( ! vis[ v] ) q. push ( v) , vis[ v] = 1 ;
flo[ v] = min ( flo[ u] , w) , pre[ v] = u, dis[ v] = dis[ u] + c, l[ v] = i;
}
}
return ( dis[ t] > ( int ) 1e9 ? - 1 : flo[ t] ) ;
}
int maxflow, mincost;
void EK ( int s, int t) {
int p;
while ( ( p= SPFA ( s, t) ) != - 1 ) {
for ( int i= t; i!= s; i= pre[ i] ) {
int r= l[ i] ;
e[ r] . w-= p, e[ r^ 1 ] . w+= p;
}
maxflow+= p;
mincost+= p* dis[ t] ;
}
}
2.Dinic
int d[ ] , cur[ ] ;
queue< int > q;
bool bfs ( int s, int t) {
memset ( d, 0x3f , sizeof ( d) ) ;
memcpy ( cur, h, sizeof ( h) ) ;
while ( q. size ( ) ) q. pop ( ) ;
q. push ( s) ; d[ s] = 0 ;
while ( q. size ( ) ) {
int u= q. front ( ) ; q. pop ( ) ;
for ( int i= h[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( ! w|| d[ v] < ( int ) 1e9 ) continue ;
q. push ( v) ;
d[ v] = d[ u] + 1 ;
if ( v== t) return 1 ;
}
}
return 0 ;
}
int dfs ( int u, int sum) {
if ( u== t) return sum;
int k, res= 0 ;
for ( int & i= cur[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w; cur[ u] = i;
if ( ! w|| d[ v] != d[ u] + 1 ) continue ;
int k= dfs ( v, min ( sum, w) ) ;
e[ i] . w-= k, e[ i^ 1 ] . w+= k;
sum-= k, res+= k;
}
return res;
}
int Dinic ( int s, int t) {
int maxflow= 0 ;
while ( bfs ( s, t) ) maxflow+= dfs ( s, INT_MAX) ;
return maxflow;
}
3.ISAP
int cur[ ] , d[ ] , pre[ ] , fa[ ] , gap[ ] ;
int ISAP ( int s, int t) {
memset ( d, 0 , sizeof ( d) ) ;
memset ( gap, 0 , sizeof ( gap) ) ;
memset ( pre, 0 , sizeof ( pre) ) ;
memset ( fa, 0 , sizeof ( fa) ) ;
memcpy ( cur, h, sizeof ( h) ) ;
gap[ 0 ] = n;
int u= s, maxflow= 0 , flag= 0 ;
while ( d[ s] < n) {
if ( u== t) {
int flow= INT_MAX;
for ( ; u!= s; u= fa[ u] )
flow= min ( flow, e[ pre[ u] ] . w) ;
for ( u= t; u!= s; u= fa[ u] )
e[ pre[ u] ] . w-= flow, e[ pre[ u] ^ 1 ] . w+= flow;
maxflow+= flow;
}
flag= 0 ;
for ( int i= cur[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v, w= e[ i] . w;
if ( ! w|| d[ u] != d[ v] + 1 ) continue ;
flag= 1 , cur[ u] = i;
pre[ v] = i, fa[ v] = u, u= v;
break ;
}
if ( flag) continue ;
int minn= n- 1 ;
for ( int i= h[ u] ; i; i= e[ i] . nxt)
if ( e[ i] . w)
minn= min ( minn, d[ e[ i] . v] ) ;
cur[ u] = h[ u] ;
if ( ! ( -- gap[ d[ u] ] ) ) break ;
gap[ ( d[ u] = minn+ 1 ) ] ++ ;
if ( u!= s) u= fa[ u] ;
}
return maxflow;
}
数据结构
1.单调队列
int q[ ] , h= 1 , t;
void solve ( int n, int a[ ] ) {
for ( int i= 1 ; i<= n; i++ ) {
while ( h<= t&& i- q[ h] >= k) h++ ;
while ( h<= t&& a[ q[ t] ] > a[ i] ) t-- ;
q[ ++ t] = i;
if ( i>= k)
}
}
2.单调栈
int st[ ] , t;
void solve ( int n, int a[ ] ) {
for ( int i= 1 ; i<= n; i++ ) {
while ( t!= 0 && a[ st[ t] ] > a[ i] )
st[ ++ t] = i;
}
}
3.ST表
struct Sparse_Table {
int st[ ] [ 25 ] ;
int op ( int t1, int t2) { return max ( t1, t2) ; }
void init ( int n, int v[ ] ) {
for ( int i= 1 ; i<= n; i++ ) st[ i] [ 0 ] = v[ i] ;
for ( int j= 1 ; ( 1 << j) <= n; j++ )
for ( int i= 1 ; i+ ( 1 << j) - 1 <= n; i++ )
st[ i] [ j] = op ( st[ i] [ j- 1 ] , st[ i+ ( 1 << j- 1 ) ] [ j- 1 ] ) ;
}
int query ( int l, int r) {
int k= log2 ( r- l+ 1 ) ;
return op ( st[ l] [ k] , st[ r- ( 1 << k) + 1 ] [ k] ) ;
}
} ;
4.珂朵莉树
struct Node {
int l, r;
mutable int v;
QWQ ( ) { l= 0 , r= - 1 , v= 0 ; }
bool operator < ( const QWQ & a) const { return l< a. l; }
} ;
struct Old_Driver_Tree {
set< Node> s;
IT spilt ( int pos) {
IT it= s. lower_bound ( ( QWQ) { pos, 0 , 0 } ) ;
if ( it!= s. end ( ) && it-> l== pos) return it;
-- it;
int l= it-> l, r= it-> r, v= it-> v;
s. erase ( it) ;
s. insert ( ( QWQ) { l, pos- 1 , v} ) ;
return s. insert ( ( QWQ) { pos, r, v} ) . first;
}
void assign ( int l, int r, int v) {
IT itr= spilt ( r+ 1 ) , itl= spilt ( l) ;
s. erase ( itl, itr) ;
s. insert ( ( QWQ) { l, r, v} ) ;
}
} ;
5.树状数组
struct Binary_Indexed_Tree {
int t[ ] ;
int lb ( int x) { return x& - x; }
void build ( ) {
for ( int i= 1 ; i<= n; ++ i) {
t[ i] += a[ i] ;
if ( i+ lb ( i) <= n) t[ i+ lb ( i) ] += t[ i] ;
}
}
int sum ( int x) { int s= 0 ; for ( int i= x; i; i-= lb ( i) ) s+= t[ i] ; return s; }
int query ( int x, int y) { return sum ( y) - sum ( x- 1 ) ; }
void add ( int x, int k) { for ( int i= x; i<= n; i+= lb ( i) ) t[ i] += k; }
} ;
6.线段树
普通
struct Node { int l, r, d, laz; } ;
struct Segment_Tree {
Node t[ 4 * ] ;
int ls ( int p) { return p<< 1 ; }
int rs ( int p) { return p<< 1 | 1 ; }
void pushup ( int p) { t[ p] . d= t[ ls ( p) ] . d+ t[ rs ( p) ] . d; }
void pushdown ( int p) {
t[ ls ( p) ] . d+= t[ p] . laz* ( t[ ls ( p) ] . r- t[ ls ( p) ] . l+ 1 ) ;
t[ rs ( p) ] . d+= t[ p] . laz* ( t[ rs ( p) ] . r- t[ rs ( p) ] . l+ 1 ) ;
t[ ls ( p) ] . laz+= t[ p] . laz, t[ rs ( p) ] . laz+= t[ p] . laz;
t[ p] . laz= 0 ;
}
void build ( int p, int l, int r) {
t[ p] . l= l, t[ p] . r= r;
if ( l== r) { t[ p] . d= a[ l] ; return ; }
int m= ( l+ r) >> 1 ;
build ( ls ( p) , l, m) ; build ( rs ( p) , m+ 1 , r) ;
pushup ( p) ;
}
void update ( int p, int l, int r, int v) {
if ( l<= t[ p] . l&& t[ p] . r<= r) {
t[ p] . d+= ( t[ p] . r- t[ p] . l+ 1 ) * v, t[ p] . laz+= v;
return ;
}
pushdown ( p) ;
int m= ( t[ p] . l+ t[ p] . r) >> 1 ;
if ( l<= m) update ( ls ( p) , l, r, v) ;
if ( r> m) update ( rs ( p) , l, r, v) ;
pushup ( p) ;
}
int query ( int p, int l, int r) {
if ( l<= t[ p] . l&& t[ p] . r<= r) return t[ p] . d;
pushdown ( p) ;
int s= 0 , m= ( t[ p] . l+ t[ p] . r) >> 1 ;
if ( l<= m) s+= query ( ls ( p) , l, r) ;
if ( r> m) s+= query ( rs ( p) , l, r) ;
return s;
}
} ;
动态开点
struct Node { int lf, rt, d, laz; } ;
struct Segment_Tree {
int root, tot;
QWQ t[ 2 * ] ;
void pushup ( int p) { t[ p] . d= t[ t[ p] . lf] . d+ t[ t[ p] . rt] . d; }
void pushtag ( int & p, int l, int r, int k) {
if ( ! p) p= ++ tot;
t[ p] . d+= ( r- l+ 1 ) * k, t[ p] . laz+= k;
}
void pushdown ( int p, int l, int r) {
int mid= ( l+ r) >> 1 ;
pushtag ( t[ p] . lf, l, mid, t[ p] . laz) ;
pushtag ( t[ p] . rt, mid+ 1 , r, t[ p] . laz) ;
t[ p] . laz= 0 ;
}
void build ( int & p, int l, int r) {
if ( ! p) p= ++ tot;
if ( l== r) { t[ p] . d= a[ l] ; return ; }
int mid= ( l+ r) >> 1 ;
build ( t[ p] . lf, l, mid) ; build ( t[ p] . rt, mid+ 1 , r) ;
pushup ( p) ;
}
void update ( int & p, int l, int r, int nl, int nr, int v) {
if ( ! p) p= ++ tot;
if ( nl<= l&& nr>= r) { pushtag ( p, l, r, v) ; return ; }
pushdown ( p, l, r) ;
int mid= ( l+ r) >> 1 ;
if ( nl<= mid) update ( t[ p] . lf, l, mid, nl, nr, v) ;
if ( nr> mid) update ( t[ p] . rt, mid+ 1 , r, nl, nr, v) ;
pushup ( p) ;
}
int query ( int p, int l, int r, int nl, int nr) {
if ( nl<= l&& nr>= r) return t[ p] . d;
pushdown ( p, l, r) ;
int mid= ( l+ r) >> 1 , res= 0 ;
if ( nl<= mid) res+= query ( t[ p] . lf, l, mid, nl, nr) ;
if ( nr> mid) res+= query ( t[ p] . rt, mid+ 1 , r, nl, nr) ;
return res;
}
} ;
李超线段树
const double eps= 1e-9 ;
struct Line {
int l, r, id; double k, b;
double f ( double x) { return k* x+ b; }
} a[ 400005 ] ;
int cnt;
struct Node { int l, r, fl; Line val; } ;
struct LiChao_Segment_Tree {
Node t[ 4 * 400005 ] ;
int ls ( int p) { return p<< 1 ; }
int rs ( int p) { return p<< 1 | 1 ; }
void build ( int p, int l, int r) {
t[ p] . l= l, t[ p] . r= r;
if ( l== r) return ;
int m= ( l+ r) >> 1 ;
build ( ls ( p) , l, m) ; build ( rs ( p) , m+ 1 , r) ;
}
int cmp ( double a, double b) { return ( a- b> eps? 1 : ( b- a> eps? - 1 : 0 ) ) ; }
void update ( int p, Line v) {
if ( v. l<= t[ p] . l&& t[ p] . r<= v. r) {
if ( ! t[ p] . fl) t[ p] . fl= 1 , t[ p] . val= v;
else {
Line & u= t[ p] . val;
int mid= ( t[ p] . l+ t[ p] . r) >> 1 ;
int bm= cmp ( v. f ( mid) , u. f ( mid) ) ;
if ( bm== 1 || ( bm== 0 && v. id< u. id) ) swap ( u, v) ;
int bl= cmp ( v. f ( t[ p] . l) , u. f ( t[ p] . l) ) , br= cmp ( v. f ( t[ p] . r) , u. f ( t[ p] . r) ) ;
if ( bl== 1 || ( bl== 0 && v. id< u. id) ) update ( ls ( p) , v) ;
if ( br== 1 || ( br== 0 && v. id< u. id) ) update ( rs ( p) , v) ;
}
return ;
}
int m= ( t[ p] . l+ t[ p] . r) >> 1 ;
if ( v. l<= m) update ( ls ( p) , v) ;
if ( v. r> m) update ( rs ( p) , v) ;
}
Line query ( int p, int x) {
if ( t[ p] . l== t[ p] . r) return t[ p] . val;
Line s= t[ p] . val; int m= ( t[ p] . l+ t[ p] . r) >> 1 ;
if ( x<= m) {
Line u= query ( ls ( p) , x) ;
if ( s. f ( x) < u. f ( x) || ( fabs ( s. f ( x) - u. f ( x) ) < eps&& s. id> u. id) ) return u;
return s;
}
else {
Line u= query ( rs ( p) , x) ;
if ( s. f ( x) < u. f ( x) || ( fabs ( s. f ( x) - u. f ( x) ) < eps&& s. id> u. id) ) return u;
return s;
}
return s;
}
} ;
7.莫队
struct Query { int l, r, id; } p[ ] ;
int a[ ] , cnt[ ] , ans[ ] , num;
bool cmp ( QWQ a, QWQ b) { return ( a. l/ num) != ( b. l/ num) ? a. l< b. l: ( ( a. l/ num) & 1 ) ? a. r< b. r: a. r> b. r; }
void add ( int i) { cur+= ( cnt[ a[ i] ] ++ == 0 ) ; }
void det ( int i) { cur-= ( -- cnt[ a[ i] ] == 0 ) ; }
void solve ( ) {
num= ( int ) sqrt ( n) ;
sort ( p+ 1 , p+ m+ 1 , cmp) ;
for ( int i= 1 ; i<= m; i++ ) {
while ( l< p[ i] . l) det ( l++ ) ;
while ( r< p[ i] . r) add ( ++ r) ;
while ( l> p[ i] . l) add ( -- l) ;
while ( r> p[ i] . r) det ( r-- ) ;
ans[ p[ i] . id] = cur;
}
}
8.treap
旋转
struct Rotate_Treap {
int l[ ] , r[ ] , v[ ] , rnk[ ] , s[ ] , w[ ] , sz, ans, rt;
void pushup ( int x) { s[ x] = s[ l[ x] ] + s[ r[ x] ] + w[ x] ; }
void lrotate ( int & k) {
int t= r[ k] ;
r[ k] = l[ t] , l[ t] = k, s[ t] = s[ k] , pushup ( k) , k= t;
}
void rrotate ( int & k) {
int t= l[ k] ;
l[ k] = r[ t] , r[ t] = k, s[ t] = s[ k] , pushup ( k) , k= t;
}
void insert ( int & k, int x) {
if ( ! k) {
k= ++ sz, s[ k] = 1 , w[ k] = 1 , v[ k] = x, rnk[ k] = rand ( ) ;
return ;
}
s[ k] ++ ;
if ( v[ k] == x) w[ k] ++ ;
if ( v[ k] < x) {
insert ( r[ k] , x) ;
if ( rnk[ r[ k] ] < rnk[ k] ) lrotate ( k) ;
}
if ( v[ k] > x) {
insert ( l[ k] , x) ;
if ( rnk[ l[ k] ] < rnk[ k] ) rrotate ( k) ;
}
}
bool del ( int & k, int x) {
if ( ! k) return false ;
if ( v[ k] == x) {
if ( w[ k] > 1 ) { w[ k] -- , s[ k] -- ; return true ; }
if ( l[ k] == 0 || r[ k] == 0 ) { k= l[ k] + r[ k] ; return true ; }
else if ( rnk[ l[ k] ] < rnk[ r[ k] ] ) { rrotate ( k) ; return del ( k, x) ; }
else { lrotate ( k) ; return del ( k, x) ; }
}
else if ( v[ k] < x) {
bool succ= del ( r[ k] , x) ;
if ( succ) s[ k] -- ; return succ;
}
else {
bool succ= del ( l[ k] , x) ;
if ( succ) s[ k] -- ; return succ;
}
}
int queryrank ( int k, int x) {
if ( ! k) return 0 ;
if ( v[ k] == x) return s[ l[ k] ] + 1 ;
else if ( x> v[ k] ) return s[ l[ k] ] + w[ k] + queryrank ( r[ k] , x) ;
else return queryrank ( l[ k] , x) ;
}
int querynum ( int k, int x) {
if ( ! k) return 0 ;
if ( x<= s[ l[ k] ] ) return querynum ( l[ k] , x) ;
else if ( x> s[ l[ k] ] + w[ k] ) return querynum ( r[ k] , x- s[ l[ k] ] - w[ k] ) ;
else return v[ k] ;
}
void querypre ( int k, int x) {
if ( ! k) return ;
if ( v[ k] < x) ans= k, querypre ( r[ k] , x) ;
else querypre ( l[ k] , x) ;
}
void querysub ( int k, int x) {
if ( ! k) return ;
if ( v[ k] > x) ans= k, querysub ( l[ k] , x) ;
else querysub ( r[ k] , x) ;
}
} ;
非旋转
struct FHQ_Treap {
int l[ 2000005 ] , r[ 2000005 ] , sz[ 2000005 ] , v[ 2000005 ] , rnk[ 2000005 ] , rt, tot;
void pushup ( int k) { sz[ k] = sz[ l[ k] ] + sz[ r[ k] ] + 1 ; }
void split ( int k, int val, int & x, int & y) {
if ( ! k) { x= y= 0 ; return ; }
if ( v[ k] <= val) x= k, split ( r[ k] , val, r[ k] , y) , pushup ( k) ;
else y= k, split ( l[ k] , val, x, l[ k] ) , pushup ( k) ;
}
int merge ( int x, int y) {
if ( ! x|| ! y) return x+ y;
if ( rnk[ x] < rnk[ y] ) { r[ x] = merge ( r[ x] , y) ; pushup ( x) ; return x; }
else { l[ y] = merge ( x, l[ y] ) ; pushup ( y) ; return y; }
}
void ins ( int val) {
int a, b; split ( rt, val, a, b) ;
sz[ ++ tot] = 1 , v[ tot] = val, rnk[ tot] = rand ( ) ;
rt= merge ( merge ( a, tot) , b) ;
}
void del ( int val) {
int a, b, c; split ( rt, val, a, c) , split ( a, val- 1 , a, b) ;
b= merge ( l[ b] , r[ b] ) , rt= merge ( merge ( a, b) , c) ;
}
int get_rank ( int val) {
int a, b, res; split ( rt, val- 1 , a, b) ;
res= sz[ a] + 1 , rt= merge ( a, b) ; return res;
}
int get_num ( int x, int k) {
if ( sz[ l[ x] ] + 1 == k) return v[ x] ;
else if ( k<= sz[ l[ x] ] ) return get_num ( l[ x] , k) ;
else return get_num ( r[ x] , k- sz[ l[ x] ] - 1 ) ;
}
int get_pre ( int val) {
int a, b, res; split ( rt, val- 1 , a, b) ;
res= get_num ( a, sz[ a] ) , rt= merge ( a, b) ; return res;
}
int get_sub ( int val) {
int a, b, res; split ( rt, val, a, b) ;
res= get_num ( b, 1 ) , rt= merge ( a, b) ; return res;
}
} ;
9.堆
手打堆
struct Heap {
int a[ ] ;
void adjust ( int p) {
int lf= INT_MAX, rt= INT_MAX, minn;
if ( p* 2 <= n) lf= a[ p* 2 ] ;
if ( p* 2 + 1 <= n) rt= a[ p* 2 + 1 ] ;
minn= min ( a[ p] , min ( lf, rt) ) ;
if ( minn== lf) {
swap ( a[ p] , a[ p* 2 ] ) ; adjust ( p* 2 ) ;
return ;
}
if ( minn== rt) {
swap ( a[ p] , a[ p* 2 + 1 ] ) ; adjust ( p* 2 + 1 ) ;
return ;
}
}
} ;
对顶堆
int sz= 0 ;
priority_queue< int , vector< int > , greater< int > > pq1;
priority_queue< int > pq2;
void adjust ( ) {
while ( pq1. size ( ) > pq2. size ( ) + 1 )
pq2. push ( pq1. top ( ) ) , pq1. pop ( ) ;
while ( pq2. size ( ) > pq1. size ( ) )
pq1. push ( pq2. top ( ) ) , pq2. pop ( ) ;
}
void add ( int x) {
if ( ! pq1. size ( ) || x>= pq1. top ( ) )
pq1. push ( x) ;
else
pq2. push ( x) ;
adjust ( ) ;
sz++ ;
}
int query ( ) {
if ( sz% 2 == 0 )
return ( pq1. top ( ) + pq2. top ( ) ) / 2 ;
return pq1. top ( ) ;
}
10.并查集
int f[ ] ;
void init ( int n) { for ( int i= 1 ; i<= n; i++ ) f[ i] = i; }
int find ( int x) { return ( x== f[ x] ? x: f[ x] = find ( f[ x] ) ) ; }
void merge ( int x, int y) { f[ find ( x) ] = find ( y) ; }
11.Trie树
int t[ ] [ ] , a[ ] , cnt;
int f ( char c) { }
void insert ( string s) {
int p= 0 , l= s. length ( ) ;
for ( int i= 0 ; i< l; ++ i) {
int r= f ( s[ i] ) ;
if ( ! t[ p] [ r] )
t[ p] [ r] = ++ cnt;
p= t[ p] [ r] ;
}
++ a[ p] ;
}
12.左偏树
struct Node { int ls, rs, key, dis, fa; } ;
struct Leftist_Tree {
Node p[ ] ;
int build ( int a[ ] , int n) {
queue< int > q; p[ 0 ] . dis= - 1 ;
for ( int i= 1 ; i<= n; i++ ) q. push ( i) , p[ ++ cnt] = { 0 , 0 , a[ i] , 0 , i} ;
while ( q. size ( ) > 1 ) {
int x= q. front ( ) ; q. pop ( ) ;
int y= q. front ( ) ; q. pop ( ) ;
q. push ( merge ( x, y) ) ;
}
return q. front ( ) ;
}
int find ( int x) { return ( x== p[ x] . fa? x: p[ x] . fa= find ( p[ x] . fa) ) ; }
int merge ( int a, int b) {
if ( ! a|| ! b) return a+ b;
if ( p[ a] . key> p[ b] . key) swap ( a, b) ;
p[ a] . rs= merge ( p[ a] . rs, b) ;
if ( p[ p[ a] . ls] . dis< p[ p[ a] . rs] . dis) swap ( p[ a] . ls, p[ a] . rs) ;
p[ p[ a] . ls] . fa= p[ p[ a] . rs] . fa= p[ x] . fa= x, p[ a] . dis= p[ p[ a] . rs] . dis+ 1 ;
return a;
}
int del ( int x) {
int ls= p[ x] . ls, rs= p[ x] . rs;
p[ ls] . fa= ls, p[ rs] . fa= rs, p[ x] . ls= p[ x] . rs= p[ x] . dis= 0 ;
return merge ( merge ( ls, rs) , find ( x) ) ;
}
} ;
13.分块
int cnt, sz, b[ ] , bel[ ] , bl[ ] , br[ ] ;
void build ( int n) {
sz= sqrt ( n) , cnt= n/ sz+ ( bool ) ( n% sz) ;
for ( int i= 1 ; i<= n; i++ )
bel[ i] = ( i- 1 ) / sz+ 1 ;
for ( int i= 1 ; i<= cnt; i++ )
bl[ i] = ( i- 1 ) * sz+ 1 , br[ i] = i* sz;
br[ cnt] = n;
}
14.Splay
struct Splay {
int l[ ] , r[ ] , f[ ] , v[ ] , sz[ ] , w[ ] , rt, tot;
void push_up ( int now) { sz[ now] = sz[ l[ now] ] + sz[ r[ now] ] + w[ now] ; }
void lrotate ( int now) {
int fa= f[ now] ; f[ now] = f[ fa] ;
if ( l[ f[ fa] ] == fa) l[ f[ fa] ] = now;
if ( r[ f[ fa] ] == fa) r[ f[ fa] ] = now;
f[ fa] = now, r[ fa] = l[ now] , f[ l[ now] ] = fa, l[ now] = fa, push_up ( fa) ;
}
void rrotate ( int now) {
int fa= f[ now] ; f[ now] = f[ fa] ;
if ( l[ f[ fa] ] == fa) l[ f[ fa] ] = now;
if ( r[ f[ fa] ] == fa) r[ f[ fa] ] = now;
f[ fa] = now, l[ fa] = r[ now] , f[ r[ now] ] = fa, r[ now] = fa, push_up ( fa) ;
}
void splay ( int now, int FA= 0 ) {
while ( f[ now] != FA) {
int fa= f[ now] ;
if ( f[ fa] == FA&& l[ fa] == now) rrotate ( now) ;
if ( f[ fa] == FA&& r[ fa] == now) lrotate ( now) ;
if ( f[ fa] != FA&& l[ f[ fa] ] == fa&& l[ fa] == now) rrotate ( fa) , rrotate ( now) ;
if ( f[ fa] != FA&& l[ f[ fa] ] == fa&& r[ fa] == now) lrotate ( now) , rrotate ( now) ;
if ( f[ fa] != FA&& r[ f[ fa] ] == fa&& l[ fa] == now) rrotate ( now) , lrotate ( now) ;
if ( f[ fa] != FA&& r[ f[ fa] ] == fa&& r[ fa] == now) lrotate ( fa) , lrotate ( now) ;
}
push_up ( now) , rt= ( FA? rt: now) ;
}
void ins ( int x) {
for ( int now= rt; ; ) {
if ( now) sz[ now] ++ ;
if ( v[ now] == x) { w[ now] ++ ; splay ( now) ; return ; }
if ( v[ now] > x)
if ( l[ now] ) now= l[ now] ;
else { l[ now] = ++ tot, sz[ tot] = 1 , f[ tot] = now, v[ tot] = x, w[ tot] = 1 , splay ( tot) ; return ; }
else
if ( r[ now] ) now= r[ now] ;
else { r[ now] = ++ tot, sz[ tot] = 1 , f[ tot] = now, v[ tot] = x, w[ tot] = 1 , splay ( tot) ; return ; }
}
}
int find ( int x) {
int now= rt;
while ( x!= v[ now] ) {
if ( v[ now] < x&& r[ now] ) now= r[ now] ;
else if ( l[ now] ) now= l[ now] ;
else break ;
}
splay ( now) ; return now;
}
int get_lower ( int x) { x= find ( x) ; for ( x= l[ x] ; r[ x] ; x= r[ x] ) ; return x; }
int get_upper ( int x) { x= find ( x) ; for ( x= r[ x] ; l[ x] ; x= l[ x] ) ; return x; }
void del ( int x) {
int ll= get_lower ( x) , rr= get_upper ( x) ;
splay ( ll) , splay ( rr, ll) ;
if ( w[ l[ rr] ] > 1 ) w[ l[ rr] ] -- , splay ( l[ rr] ) ;
else l[ rr] = 0 ;
push_up ( rr) , push_up ( ll) ;
}
int get_rank ( int x) { splay ( x) ; return sz[ l[ x] ] + 1 ; }
int get_num ( int k) {
for ( int now= rt; ; ) {
if ( sz[ l[ now] ] + 1 > k&& l[ now] ) now= l[ now] ;
else if ( sz[ l[ now] ] + w[ now] < k&& r[ now] ) k-= sz[ l[ now] ] + w[ now] , now= r[ now] ;
else { splay ( now) ; return now; }
}
}
} ;
15.线性基
int d[ ] ;
void add ( int x) {
for ( int i= 31 ; i>= 0 ; i-- ) {
if ( x& ( 1 << i) ) {
if ( ! d[ i] ) { d[ i] = x; return ; }
x^= d[ i] ;
}
}
}