title: csp算法模板
线性筛素数
void sieve(){
fill(isprime+1,isprime+n,true);
for( int i = 2 ; i <= N ; i ++){
if(isprime[i])
prime[ ++ num ] = 2;
for(int j = 1 ; j <= num && i * prime[ j ] <= N ; j ++){
isprime[ i * prime[ j ] ] = false;
// smallest_prime[ i * prime[ j ] ] = prime[ j ] ;
if( i % prime[ j ] == 0 )
break;
}
}
}
树状数组
void add(int x , int v ){
for(int i = x ; i <= N ; i += lowbit(i) ){
tr[i] += v;
}
}
void get_sum( int x ){//1到x
int sum = 0;
while(x){
sum += tr[x];
x -= lowbit(x);
}
return x;
}
/*************/
//区间求和,单点修改
for(int i = 1 ; i <= N ; i ++ ){
add(i , a[i] );
}
get_sum(x);
add( x , v );//1到x
/**************/
//单点求和,区间修改,差分,a[i]=a[i]-a[i-1]
get_sum(x)+a[x];
add( x , v );
add( y + 1 , -v );
/*************/
单源最短路-Dijkstra
struct for_dij{
int to,v;
bool operator <(const for_dij &b) const {//堆默认是大根堆,因此重载<要反过来,堆内部实现只用了小于号
return b.v < v;
}
};
struct node{
int to, w;
};
vector <node> edge[N];
bool book[N];
int dis[N];
void dijkstra(int a){
memset(book,0,sizeof book);
fill(dis+1,dis+n,0x7fffffff);
priority_queue <for_dij> q;//堆优化
q.push((for_dij){a,0});
dis[a]=0;
/*****************核心*****/
while(!q.empty()){
int u = q.top().to,value=q.top().v; q.pop();
if(dis[u]!=value)//很重要的优化,剪掉“过时”的点
continue;
book[u]=true;
for(int i = 0 ; i < edge[u].size(); i ++){
int v =edge[u][i].to,w=edge[u][i].w;
if(book[v]) continue;
if( dis[v]>dis[u]+w){
dis[v] = dis[u] + w;
q.push((for_dij){v,dis[v]});
}
}
}
/******************/
}
for(int i = 1 ; i <= m ; i ++ ){
int u,v,w;
cin>>u>>v>>w;
edge[u].push_back((node){v,w});
edge[v].push_back((node){u,w});//双向
}
矩阵快速幂
//用于优化递推,dp
struct matrix{
int g[N][N];
matrix(){
memset(g,0,sizeof g);
}
matrix operator *(const matrix &a) const{
matrix c;
for(int k = 1 ; k <= N ; k ++ )
for(int i = 1; i <= N ; i ++ )
for(int j = 1; j <= N ; j ++ )
c.g[i][j]=(c.g[i][j]+g[i][k]*a.g[k][j]%mod)%mod;
return c;
}
}S,E;
//E是初始矩阵
//S是用于递推的矩阵
matrix poww(k){
while(k){
if(k&1) E = E * S;
k >>= 1;
S = S * S;
}
return E;
}
单调队列
寻找窗口内最大元素,定义一个单调队列q,和下标数组p
-
队列外的元素a与队列尾部元素b比较大小(队列为空时直接入队)
- 若a>=b,则队尾元素出队
- 若a<b,则a直接进队。
-
比较队首元素下标与窗口左端下标,队首元素出队直至队首元素下标>窗口左端下标
-
此时队首元素为该窗口内的最大元素
#define maxn 1001000
int q[ maxn ] , p[ maxn ] , n , k ,a[ maxn ];
int main ()
{
ios::sync_with_stdio( false ) ;
cin >> n >> k ;
head = 1 , tail = 0 ; cout << endl ;
for ( int i = 1 ; i <= n ; i ++ )
{
while ( head <= tail && q[ tail ] < a[ i ] )
tail -- ;
q[ ++ tail ] = a[ i ] ;
p[ tail ] = i ;//以上对应步骤1
while ( p[ head ] <= i - k ) head ++ ;//将队列下标与窗口左端对齐,对应步骤2
if ( i >= k ) cout << q[ head ] << ' ' ;
}
}
并查集
int find(a){
if(fa[a]!=a) fa[a]=find(fa[a]);//路径压缩
return a;
}
void merge(int a,int b){
a= find(a);b=find(b);
fa[a]=b;
}
最小生成树
prim
//本质上核dijkstra没区别
void prim(int a){
memset(book,0,sizeof book);
fill(dis+1,dis+n,0x7fffffff);
priority_queue <for_dij> q;//堆优化
q.push((for_dij){a,0});
dis[a]=0;
/*****************核心*****/
while(!q.empty()){
int u = q.top().to,value=q.top().v; q.pop();
if(dis[u]!=value)//很重要的优化,剪掉“过时”的点
continue;
book[u]=true;
mst += dis[u];//mst求最小生成树的所有边权
for(int i = 0 ; i < edge[u].size(); i ++){
int v =edge[u][i].to,w=edge[u][i].w;
if(book[v]) continue;
if( dis[v]>dis[u]+w){
dis[v] = w;//除了原点,每个点存个最小生成树的边
q.push((for_dij){v,dis[v]});
}
}
}
/******************/
}
最近公共祖先
//***********//链式前向星
struct node{
int to , nex;
}edge[ m * 2 ];//双向路径边变两倍
void add_side( int u , int v , int w ){
edge[ ++ num ] = { v , hea[ u ], w };
hea[ u ] = num ;
edge[ ++ num ] = { u , hea[ v ], w };
hea[ v ] = num ;
}
void init( int s ){
dep[ s ] = 1 ;
for(int i = 2 ; i <= n ; i ++ )
lg[ i ] = lg[ i - 1 ] + ( 1 << lg[ i - 1 ] == i - 1 ) ;
}
void dfs( int u ){//算是预处理吧
for( int i = hea[ u ] ; i ; i = edge[ i ].nex ){
int v = edge[ i ].to ;
if( dep [ v ]) continue ;
dep[ v ] = dep[ u ] + 1;
f[ v ][ 0 ] = u ;
for( int j = 1 ; j <= lg[ dep[ v ] ] ; j ++ )
f[ v ][ j ] = f[ f[ v ][ j - 1 ] ][ j - 1 ] ;
dfs( v ) ;
}
}
int lca( int a , int b ){
if( dep[ a ] < dep[ b ] )
swap( a , b );
while( dep[ a ] > dep[ b ])
a = f[ a ][ lg[ dep[ a ] - dep [ b ] ] ] ;
if( a == b ) return a ;
for( int k = lg[ dep[ a ] ] ; k >= 0 ; k -- ){
if( f[ a ][ k ] != f[ b ][ k ] )
a = f[ a ][ k ], b = f[ b ][ k ];
}
return f[ a ][ 0 ];
}