zoukankan      html  css  js  c++  java
  • 一些模板

    模板太多了,写啥更新啥,顺便当自己的存档

    码风很乱,见谅


    单点修改树状数组

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    #define l() i&-i
    using namespace std;
    
    int n,m,a[500010],tree[500010],c,x,y;
    
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    
    inline void updata(int x,int k)
    {
        for(int i=x;i<=n;i+=lowbit(x))
            tree[i]+=k;
    }
    
    inline int query(int x)
    {
        int ans=0;
        for(int i=x;i;i-=lowbit(x))
            ans+=tree[i];
        return ans;
    }
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    int main()
    {
        n=read();
        m=read();
        for(int i=1;i<=n;i++)
        {
            a[i]=read();
            updata(i,a[i]);
        }
        for(int i=1;i<=m;i++)
        {
            c=read();
            if(c==1)
            {
                x=read();
                y=read();
                updata(x,y);
            }
            else
            {
                x=read();
                y=read();
                cout<<query(y)-query(x-1)<<endl;
            }
        }
    }

    区间修改树状数组

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    #define l() i&-i
    using namespace std;
    
    int n,x,y,z,k,tree[500010],a,m,last=0;
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    inline int lowbit(int x)
    {
        return x&(-x);
    }
    inline void add(int x,int k)
    {
        for(int i=x;i<=n;i+=lowbit(i))
            tree[i]+=k;
    }
    
    inline long long query(int x)
    {
        long long ans=0;
        for(int i=x;i;i-=lowbit(i))
            ans+=tree[i];
        return ans;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            a=read();
            add(i,a-last);
            last=a;
        }
        for(int i=1;i<=m;i++)
        {
            cin>>x;
            if(x==1)
            {
                cin>>y>>z>>k;
                add(y,k);
                add(z+1,-k);
            }
            if(x==2)
            {
                cin>>y;
                cout<<query(y)<<endl;
            }
        }
    }

    可持久化线段树(主席树)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    using namespace std;
    
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    int n,q,m,T[200001],tot,a[200001],b[200001];
    struct cym{
        int l,r,val;
    }tree[8000001];
    
    inline int bulid(int l,int r)// 建树操作 
    {
        int bj=++tot;
        tree[bj].val=0;
        int mid=(l+r)>>1;
        if(l>r)
        {
            tree[bj].l=bulid(l,mid);
            tree[bj].r=bulid(mid+1,r);
        }
        return bj;
    }
    
    inline int change(int pre,int l,int r,int zone)// 修改 
    {
        int bj=++tot;
        tree[bj].l=tree[pre].l;
        tree[bj].r=tree[pre].r;
        tree[bj].val=tree[pre].val+1;
        int mid=(l+r)>>1;
        if(l<r)
        {
            if(zone<=mid)
                tree[bj].l=change(tree[pre].l,l,mid,zone);
            else
                tree[bj].r=change(tree[pre].r,mid+1,r,zone);
        }
        return bj;
    }
    
    inline int cx(int from,int to,int l,int r,int k)// 查询 
    {
        if(l==r)
            return l;
        int x=tree[tree[to].l].val-tree[tree[from].l].val;
        int mid=(l+r)>>1;
        if(x>=k)
            return cx(tree[from].l,tree[to].l,l,mid,k);
        else
            return cx(tree[from].r,tree[to].r,mid+1,r,k-x);
    }
    int main()
    {
        n=read(),q=read();
        for(rg int i=1;i<=n;i++)
        {
            a[i]=read();
            b[i]=a[i];
        }
        sort(b+1,b+n+1);// 排序 
        m=unique(b+1,b+n+1)-b-1;// 看一共有多少个不重复的元素 
        T[0]=bulid(1,m);// 把最后一个点建在 主席树数组T[0]的位置  
        for(rg int i=1;i<=n;i++)
        {
            int t=lower_bound(b+1,b+m+1,a[i])-b;// 第一个比a[i] 大的树的位置 
            T[i]=change(T[i-1],1,m,t);
        }
        for(rg int i=1;i<=q;i++)
        {
            int l=read(),r=read(),k=read();
            int anss=cx(T[l-1],T[r],1,m,k);
            printf("%d
    ",b[anss]);
        }
    }

     ST表

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int MAXN=1e6+10;
    inline int read()
    {
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int Max[MAXN][21];
    int Query(int l,int r)
    {
        int k=log2(r-l+1); 
        return max(Max[l][k],Max[r-(1<<k)+1][k]);//把拆出来的区间分别取最值 
    }
    int main()
    {
    
        int N=read(),M=read();
        for(int i=1;i<=N;i++) Max[i][0]=read();
        for(int j=1;j<=21;j++)
            for(int i=1;i+(1<<j)-1<=N;i++)//注意这里要控制边界 
                Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);//如果看不懂边界的话建议好好看看图 
        for(int i=1;i<=M;i++)
        {
            int l=read(),r=read();
            printf("%d
    ",Query(l,r));
        }
        return 0;
    }

     Kruskal

    /*
                Kruskal
                并查集
                结构体存边 
                luogu P3366 模板 
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    using namespace std;
    
    int n,m,ans,now_e,now_v,cnt;
    
    inline int read()// 读入优化 
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    struct Node{
        int start,end,power;
        // start为起始点
        // end 为终点 
        // power 为权值 
    }edge[2000010];// 存边 
    int fa[6666];//并查集 
    
    int cmp(Node a,Node b)
    {
        return a.power<b.power; 
    }
    
    inline int find(int x)// 并查集找祖先 
    {
        if(x!=fa[x])
        {
            fa[x]=find(fa[x]);
        }
        return fa[x];
    }
    
    /*inline void merge(int x,int y,int n)// 并查集合并
    // n用来记录最短路中应该加入哪个点 
    {
        int fx=find(x);
        int fy=find(y);
        if(fx!=fy)
        {
            pre[fx]=fy;
            sum+=edge[n].power;
        }
    }*/
    
    inline void Kruskal()
    {
        sort(edge+1,edge+1+m,cmp);// 排序
        for(rg int i=1;i<=m;i++)
        {
            now_e=find(edge[i].start);
            now_v=find(edge[i].end);
            if(now_e==now_v)
                continue;//若两点联通 就不需要了 
            ans+=edge[i].power;
            fa[now_v]=now_e;//合并
            if(++cnt==n-1)
                break;// 边数==点数-1 就结束循环 
        } 
    }
    int main()
    {
        n=read(),m=read();
        for(rg int i=1;i<=n;i++)
        {
            fa[i]=i;// 并查集初始化 
        }
        for(rg int i=1;i<=m;i++)
        {
            edge[i].start=read();
            edge[i].end=read();
            edge[i].power=read();
        }
        Kruskal();
        printf("%d",ans);
    }

     Prim

    /*
                Prim
                链式前向星存图 
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    #define inf 0x7ffffff
    using namespace std;
    
    int head[5005],dis[5005],cnt,n,m,tot,now=1,ans;
    bool vis[5005];
    
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    struct Node{
        int v,w,next;
    }e[400010];
    
    inline void add(int u,int v,int w)
    {
        e[++cnt].v=v;
        e[cnt].w=w;
        e[cnt].next=head[u];
        head[u]=cnt;
    }
    inline int prim()
    {
        for(rg int i=2;i<=n;i++)
            dis[i]=inf;
        for(rg int i=head[1];i;i=e[i].next)
        {
            dis[e[i].v]=min(dis[e[i].v],e[i].w);
        }
        while(++tot<n)//最小生成树边数==点数-1
        {
            rg int minn=inf;
            vis[now]=1;//标记点已经走过
            for(rg int i=1;i<=n;i++)
            {
                if(!vis[i]&&minn>dis[i])
                {
                    minn=dis[i];
                    now=i;
                }
             } 
             ans+=minn;
             //枚举now的连边,更新dis 
             for(rg int i=head[now];i;i=e[i].next)
             {
                rg int v=e[i].v;
                if(dis[v]>e[i].w&&!vis[v])
                {
                    dis[v]=e[i].w;
                    }    
             }         
         } 
         return ans;
    }
    int main()
    {
        n=read(),m=read();
        for(rg int i=1,u,v,w;i<=m;i++)
        {
            u=read(),v=read(),w=read();
            add(u,v,w),add(v,u,w);//无向图 
        }
        printf("%d",prim());
    }

    稀疏图:Kruskal

    稠密图:Prim

     Dijkstra

    /*
                Dijkstra
                朴素:O(n^2)
                堆优化:O((n+m)log^2n)
                不可以处理负边权的图
                luogu P4799 模板 
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #define ll long long
    #define rg register
    using namespace std;
    
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    struct Node{
        int v,w,next;
    }e[500010];
    
    int head[100010],dis[100010],cnt;
    bool vis[100010];
    int n,m,s;
    
    inline void add(int u,int v,int dis)
    {
        e[++cnt].v=v;
        e[cnt].w=dis;
        e[cnt].next=head[u];
        head[u]=cnt;
    }
    
    struct node{
        int dis;//
        int pos;// 位置 
        bool operator <( const node &x)const
        {
            return x.dis<dis;
        }
    }; // 堆优化
    
    priority_queue<node>q;
    
    inline void dij()//名字太长了 容易打错 简写dij 
    {
        dis[s]=0;
        q.push((node){0,s});
        while(!q.empty())
        {
            node tmp=q.top();
            q.pop();
            int x=tmp.pos,d=tmp.dis; 
            if(vis[x])
                continue;
            vis[x]=1;
            for(int i=head[x];i;i=e[i].next)
            {
                int y=e[i].v;
                if(dis[y]>dis[x]+e[i].w)
                {
                    dis[y]=dis[x]+e[i].w;
                //    if(!vis[y])
                    //{
                        q.push(node{dis[y],y});
                //    }
                }
            }
        }
    } 
    
    int main()
    {
        n=read(),m=read(),s=read();
        for(rg int i=1;i<=n;i++)
            dis[i]=2147482647;// 尽量赋值大一点 防止答案超过这个数!!!
        for(rg int i=1,u,v,d;i<=m;i++)
        {
            u=read(),v=read(),d=read();
            add(u,v,d);
        }
        dij();
        for(int i=1;i<=n;i++)
            printf("%d ",dis[i]);
    }

     倍增版LCA

    /*
                LCA
                倍增 
    */
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    #define rg register
    using namespace std;
    
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    struct cym{
        int t,nex;
    }e[1000001];
    
    int depth[500001],fa[500001][22],lg[500001],head[500001],n,m,s;
    int cnt;
    
    inline void add(int x,int y)
    {
        e[++cnt].t=y;
        e[cnt].nex=head[x];
        head[x]=cnt;
    }
    
    void dfs(int f,int fath)// f 表示当前的节点,fath 表示他的父亲节点 
    {
        depth[f]=depth[fath]+1;
        fa[f][0]=fath;
        for(rg int i=1;(1<<i)<=depth[f];i++)
            fa[f][i]=fa[fa[f][i-1]][i-1];// 核心转移 
            // f的2^i祖先=f的2^(i-1)的祖先的2(i-1)祖先
            //2^i=2^(i-1)+2^(i-1)
        for(rg int i=head[f];i;i=e[i].nex)
            if(e[i].t!=fath)
                dfs(e[i].t,f); 
    }
    
    inline int lca(int x,int y)
    {
        if(depth[x]<depth[y])// 我们不妨设x的深度>=y的深度
            swap(x,y);
        while(depth[x]>depth[y])
            x=fa[x][lg[depth[x]-depth[y]]-1];//先跳到同一深度
        if(x==y)
            return x;// 如果x是y的祖先,那他们的lca就是x
        for(rg int k=lg[depth[x]]-1;k>=0;k--)
        {
            if(fa[x][k]!=fa[y][k])
                x=fa[x][k],y=fa[y][k];
        } 
        return fa[x][0];//返回父节点 
    }
    
    int main()
    {
        n=read(),m=read(),s=read();
        for(rg int i=1,x,y;i<=n-1;i++)
        {
            x=read(),y=read();
            add(x,y);
            add(y,x);
        }
        dfs(s,0);
        for(rg int i=1;i<=n;i++)
            lg[i]=lg[i-1]+(1<<lg[i-1]==i);
        // 预处理log2i +1的值 直接调用
         for(rg int i=1,x,y;i<=n;i++)
         {
             x=read(),y=read();
             printf("%d
    ",lca(x,y));
         }
    }

     区间M的最小值(单调队列优化Dp)

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    //#include <windows.h>
    #define ll long long
    #define rg register
    #define ull unsigned long long 
    
    using namespace std;
    
    int n,m;
    int k,tot,head=1,tail=0;
    int a[2000009],q[2000009];
    
    inline int read()
    {
        int x=0,f=1;
        char ch;
        while (ch < '0' || ch > '9')  {if (ch=='-')f = -1;ch = getchar();}
        while (ch >= '0' && ch <= '9'){x = x*10+ch-'0';ch = getchar();}
        return f*x;
    }
    
    int main()
    {
        n=read(),m=read();
        for(rg int i=1;i<=n;i++)
            a[i]=read();
        for(rg int i=1;i<=n;i++)
        {
            printf("%d
    ",a[q[head]]);
            while(i-q[head]+1>m&&head<=tail)    
                head++;
            while(a[i]<a[q[tail]]&&head<=tail)
                tail--;
            q[++tail]=i;
        }
        //system("pause");
        return 0;
    }
  • 相关阅读:
    架构,改善程序复用性的设计(目录)
    如何让你的系统配置文件更合理
    MVC验证(自动在基类中验证实体的数据有效性),本人最满意的作品之一
    MVC验证(只验证指定字段)
    Redis学习笔记~实现消息队列比MSMQ更方便
    FRG图像文件格式(四):编码技术
    缓冲区
    Oracle体系结构及备份(十一)——bcakgroundprocess
    Excel编程(2)自动填充
    设计模式:策略模式
  • 原文地址:https://www.cnblogs.com/_Yrh/p/10339620.html
Copyright © 2011-2022 走看看