• csp复习笔记?



    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;
    }
    

    单调队列

    P1886滑动窗口

    寻找窗口内最大元素,定义一个单调队列q,和下标数组p

    1. 队列外的元素a与队列尾部元素b比较大小(队列为空时直接入队)

      • 若a>=b,则队尾元素出队
      • 若a<b,则a直接进队。
    2. 比较队首元素下标与窗口左端下标,队首元素出队直至队首元素下标>窗口左端下标

    3. 此时队首元素为该窗口内的最大元素

    #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 ];
    }
    
    
  • 相关阅读:
    auto-sklearn案例解析二
    auto-sklearn案例解析二
    auto-sklearn案例解析一
    auto-sklearn案例解析一
    auto-sklearn简介
    auto-sklearn简介
    auto-sklearn手册
    auto-sklearn手册
    观念
    JDBC总结
  • 原文地址:https://www.cnblogs.com/nothatdinger/p/13649642.html
Copyright © 2020-2023  润新知