• 面试前夕oi挣扎式复习


    • 线段树

    void PushUp(ll rt){
        Sum[rt]=Sum[rt<<1]+Sum[rt<<1|1];
    }
    void Build(ll l,ll r,ll rt){
        if(l==r){
            Sum[rt]=A[l];
            return ;
        }
        ll m=(l+r)>>1;
        Build(l,m,rt<<1);
        Build(m+1,r,rt<<1|1);
        PushUp(rt);
    }
    void PushDown(ll rt,ll ln,ll rn){//下推标记 
        if(Add[rt]){
            Add[rt<<1]+=Add[rt];
            Add[rt<<1|1]+=Add[rt];
            Sum[rt<<1]+=Add[rt]*ln;
            Sum[rt<<1|1]+=Add[rt]*rn;
            Add[rt]=0;//清除标记 
        }
    }
    void Update(ll L,ll R,ll C,ll l,ll r,ll rt){//区间修改 
        if(L<=l&&r<=R){//如果[l,r]区间完全在操作区间[L,R]以内
            Sum[rt]+=C*(r-l+1);
            Add[rt]+=C;
            return ;
        }
        ll m=(l+r)>>1;
        PushDown(rt,m-l+1,r-m);
        if(L<=m)Update(L,R,C,l,m,rt<<1);
        if(R>m) Update(L,R,C,m+1,r,rt<<1|1);
        PushUp(rt);
    }
    ll Query(ll L,ll R,ll l,ll r,ll rt){//区间求和 
        if(L<=l&&r<=R){//在区间内直接返回 
            return Sum[rt];
        }
        ll m=(l+r)>>1;
        PushDown(rt,m-l+1,r-m);
        ll ANS=0;
        if(L<=m)ANS+=Query(L,R,l,m,rt<<1);
        if(R>m) ANS+=Query(L,R,m+1,r,rt<<1|1);
        return ANS;
    }
    • 树状数组

    inline ll lowbit(ll x) {return x&-x;}
    inline void add(int x,ll k)
    {
        while(x<=n)
        {
            a[x]+=k;x+=lowbit(x);
        }
    }
    inline ll find(int x)
    {
        ll sum=0;
        while(x)
        {
            sum+=a[x];x-=lowbit(x);
        }
        return sum;
    }
    • tarjan缩点

    void dfs(int u)
    {
        dfn[u]=low[u]=++tot;
        vis[u]=1;sta[++top]=u;
        for(int j=head[u];j;j=e[j].nxt)
        {
            int v=e[j].v;
            if(!dfn[v])
            {
                dfs(v);low[u]=min(low[u],low[v]);
            }
            else if(vis[v]) low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
        {
            int x;
            while(1)
            {
                x=sta[top--];vis[x]=0;
                fa[x]=u;if(x==u)break;
                a[u]+=a[x];
            }
        }
    }
    • 线性基

       for(int i=1;i<=n;i++)
        {
            scanf("%lld",&x);
            for(int k=62;k>=0;k--)if((1LL<<k)&x)
            {
                if(!xx[k]) {xx[k]=x;break;} 
                x^=xx[k];
            }
        }
        ll ans=0;
        for(int k=62;k>=0;k--) if((ans^xx[k])>ans) ans^=xx[k];
    • ST表

        lg[0]=-1;
        for(int i=1;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++) 
        {
            scanf("%d",&f[0][i]);
        }
        for(int j=1;j<=20;j++) 
        for(int i=1;i+(1<<j)-1<=n;i++) f[j][i]=max(f[j-1][i],f[j-1][i+(1<<(j-1))]);
        int x,y,k;
        while(m--)
        {
            scanf("%d%d",&x,&y);
            k=lg[y-x+1];
            printf("%d
    ",max(f[k][x],f[k][y-(1<<k)+1]));
        }    
    • 并查集

    inline int get(int x) {return x==fa[x]?x:fa[x]=get(fa[x]);} 
    • 欧拉筛

    void GetPrime(int n)//筛到n
    {
        memset(isPrime, 1, sizeof(isPrime));
        //以“每个数都是素数”为初始状态,逐个删去
        isPrime[1] = 0;//1不是素数
        
        for(int i = 2; i <= n; i++)
        {
            if(isPrime[i])//没筛掉 
                Prime[++cnt] = i; //i成为下一个素数
                
            for(int j = 1; j <= cnt && i*Prime[j] <= n/*不超上限*/; j++) 
            {
                //从Prime[1],即最小质数2开始,逐个枚举已知的质数,并期望Prime[j]是(i*Prime[j])的最小质因数
                //当然,i肯定比Prime[j]大,因为Prime[j]是在i之前得出的
                isPrime[i*Prime[j]] = 0;
                
                if(i % Prime[j] == 0)//i中也含有Prime[j]这个因子
                    break; //重要步骤。见原理
            }
        }
    }
    • 网络流最大流

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=1e4+50,M=1e5+50;
    struct pp
    {
        int v,nxt,c;
    }e[M<<2];
    int tot=1,n,m,st,ed;
    int head[N],dep[N],gap[N];
    void add(int u,int v,int c)
    {
        e[++tot].nxt=head[u];head[u]=tot;
        e[tot].v=v;e[tot].c=c;
        e[++tot].nxt=head[v];head[v]=tot;
        e[tot].v=u;e[tot].c=0;
    }
    void bfs()
    {
        memset(dep,-1,sizeof(dep));
        gap[dep[ed]=0]=1;
        queue<int> q;q.push(ed);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int j=head[u];j;j=e[j].nxt)
            {
                int v=e[j].v;
                if(dep[v]!=-1) continue;
                q.push(v);gap[dep[v]=dep[u]+1]++;
            }
        }
    }
    int dfs(int u,int flow)
    {
        if(u==ed) return flow;
        int s=0,val;
        for(int j=head[u];j;j=e[j].nxt)
        {
            int v=e[j].v,c=e[j].c;
            if(c<=0||dep[v]!=dep[u]-1)continue;
            s+=(val=dfs(v,min(c,flow-s)));
            e[j].c-=val;e[j^1].c+=val;
            if(s==flow) return s;
        }
        gap[dep[u]]--;
        if(gap[dep[u]]==0) dep[st]=n+1;
        gap[++dep[u]]++;
        return s;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&st,&ed);
        for(int i=1,u,v,c;i<=m;i++)
        {
            scanf("%d%d%d",&u,&v,&c);
            add(u,v,c);
        }
        bfs();
        int res=0;
        while(dep[st]<n) res+=dfs(st,233333333L);
        printf("%d
    ",res);
        return 0;
    }
    • 快速矩阵幂

    struct Mat
    {
        ll m[N][N];
        Mat operator = (int x)
        {
            for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) 
            m[i][j]=(i==j&&x);    return *this;
        }
        Mat operator * (Mat b)
        {
            Mat a=*this,c;c=0;
            for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++) (c.m[i][j]+=(a.m[i][k]*b.m[k][j]))%=MOD;
            return c;
        }
        Mat operator ^ (ll b)
        {
            Mat a=*this,c;c=1;
            for(;b;b>>=1) {if(b&1) c=c*a;a=a*a;} 
            return c;
        }
    } d;
    void print(Mat a)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)  printf("%lld ",a.m[i][j]);printf("
    ");
        }
    }
    • 最小费用最大流

    #include<queue>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=5050,M=50050;
    struct pp
    {
        int v,nxt,d,c;
    }e[M<<1];
    int head[N],flow[N],tot=1,pre[N],dis[N];
    bool vis[N];
    int n,m,st,ed;
    long long res,ans;
    int min(int a,int b)
    {
        return a>b?b:a;
    }
    void add(int u,int v,int c,int d)
    {
        e[++tot].nxt=head[u];head[u]=tot;
        e[tot].v=v;e[tot].d=d;e[tot].c=c;
        e[++tot].nxt=head[v];head[v]=tot;
        e[tot].v=u;e[tot].d=-d;e[tot].c=0;
    }
    bool spfa()
    {
        queue<int> q;q.push(st);
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;flow[st]=233333333L;
        while(!q.empty())
        {
            int u=q.front();q.pop();vis[u]=0;
            for(int j=head[u];j;j=e[j].nxt)
            {
                int v=e[j].v,c=e[j].c,d=e[j].d;
                if(c<=0) continue;
                if(dis[v]>dis[u]+d)
                {
                    dis[v]=dis[u]+d;
                    pre[v]=j;
                    flow[v]=min(flow[u],c);
                    if(!vis[v])
                        vis[v]=1,q.push(v);
                }
            }
        }
        if(dis[ed]==dis[0]) return 0;
        int mn=233333333L;
        for(int x=ed,j;x!=st;x=e[j^1].v)
            j=pre[x],mn=min(mn,flow[x]);
        res+=1LL*mn*dis[ed];
        ans+=1LL*mn;
        for(int x=ed,j;x!=st;x=e[j^1].v)
        {
            j=pre[x];
            e[j].c-=mn;
            e[j^1].c+=mn;
        }
        return 1;
    }
    int main()
    {
        scanf("%d%d%d%d",&n,&m,&st,&ed);
        for(int i=1;i<=m;i++)
        {
            int u,v,c,d;
            scanf("%d%d%d%d",&u,&v,&c,&d);
            add(u,v,c,d);
        }
        while(spfa());
        printf("%lld %lld
    ",ans,res);
        return 0;
    }
    • 最近公共祖先LCA

    void dfs(int u,int la)
    {
        f[u][0]=la;dep[u]=dep[la]+1;
        for(int i=1;i<=lg[dep[u]];i++)
            f[u][i]=f[f[u][i-1]][i-1];
        for(int j=head[u];j;j=e[j].nxt)
        {
            int v=e[j].v;
            if(v==la) continue;
            dfs(v,u);
        }
    }
    int lca(int x,int y)
    {
        if(dep[x]<dep[y]) x^=y^=x^=y;
        while(dep[x]>dep[y])
            x=f[x][lg[dep[x]-dep[y]-1]];
        if(x==y) return x;
        for(int k=lg[dep[x]];k>=0;k--)
            if(f[x][k]!=f[y][k])
                x=f[x][k],y=f[y][k];
        return f[x][0];
    }
    • dijkstra

    void dijkstra()
    {
        memset(dis,127/3,sizeof(dis));
        dis[s]=0;
        q.push((qq){s,0});
        while(!q.empty())
        {
            qq x=q.top();q.pop();
            int u=x.u;
            if(vis[u]) continue;
            vis[u]=1;
            for(int j=head[u];j;j=e[j].nxt)
            {
                int v=e[j].to,d=e[j].d;
                if(dis[v]>dis[u]+d)
                {
                    dis[v]=dis[u]+d;
                    q.push((qq){v,dis[v]});
                }
            }
        }
    }
    • spfa

    void spfa()
    {
      queue<int> q; //spfa用队列,这里用了STL的标准队列
      for(int i=1; i<=n; i++) 
      {
        dis[i]=inf; //带权图初始化
        vis[i]=0; //记录点i是否在队列中,同dijkstra算法中的visited数组
      }
      q.push(s); dis[s]=0; vis[s]=1; //第一个顶点入队,进行标记
      while(!q.empty())
      {
        int u=q.front(); //取出队首
        q.pop(); vis[u]=0; //出队标记
        for(int i=head[u]; i; i=edge[i].next) //邻接表遍历,不多解释了(也可用vector代替)
        {
          int v=edge[i].to; 
          if(dis[v]>dis[u]+edge[i].dis) //如果有最短路就更改
          {
            dis[v]=dis[u]+edge[i].dis;
            if(vis[v]==0) //未入队则入队
            {
              vis[v]=1; //标记入队
              q.push(v);
            }
          }
        }
      }
    }
    • 二分图匹配

    bool Dfs(int u,int t)  // t为时间戳  
    {
        for(int j=head[u];j;j=e[j].nxt)
        {
            int v=e[j].v;
            if(vis[v]^t) // 要是 vis 和 t 不相等说明本次 dfs 还没用到 v  
            {
                vis[v]=t;
                if((!f[v])||Dfs(f[v],t))
                {
                    f[v]=u;
                    return 1;
                }
            }
        }
        return 0;
    }
    • exgcd

    void exgcd(ll a, ll b, ll& x, ll& y, ll& c)
    {
         if(!b) {y = 0; x = 1; c = a; return;}
         exgcd(b, a % b, y, x); y -= a / b * x;
    }
  • 相关阅读:
    资料收集
    layui 设计资源——2.0 版本的 Axure 组件包,产品交互设计利器
    照片自动按时间分类助手
    回顾2017,规划2018,展望2019
    coder/programmer engineer Chirf Technology Offcer
    新手开公司创业,这些坑千万别掉进去!
    ASP.NET MVC中的Global.asax文件
    SQLServer(MSSQL)、MySQL、SQLite、Access相互迁移转换工具 DB2DB v1.0
    快速开发之代码生成器(asp.net mvc4 + easyui + knockoutjs)
    PowerDesigner逆向工程导入MYSQL数据库总结
  • 原文地址:https://www.cnblogs.com/lxy8584099/p/12907263.html
Copyright © 2020-2023  润新知