zoukankan      html  css  js  c++  java
  • 技能树

     STL:


    容器与迭代器的概念
    重载运算符

    vector:
    v.size();
    v.push_back();
    v[i];

    set:
    set.insert();
    set.erase();
    set.begin();
    set.end();指到最后一个的后一个
    set.count();
    set.lower_bound();
    set.upper_bound();
    set.size();

    priority_queue:
    Q.push();
    Q.pop();
    Q.size();
    Q.top();
    实现普通堆

    multiset:
    和set类似,删除的时候特别注意

    string:
    动态开空间

    deque:
    deq.front();
    deq.back();
    deq.push_front(x);
    deq.pop_front();
    deq.push_back(x);
    deq.pop_back();

    lower_bound();
    upper_bound();

    string:
    动态开空间

    重载运算符:

    bool operator < (const Vergil &x) const
    {
    }

     //https://vjudge.net/problem/UVA-10815

    图与数据结构


    建图 :邻接矩阵  邻接表

    图的dfs和bfs :    //魔板

    二分图染色: //封锁阳光大学

    最短路: SPFA&&dij

    // 差分约束系统

    dij模板:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define maxn 500005
    struct Vergil
    {
        int id,d;
        bool operator < (const Vergil &a) const
        {
            return d>a.d;
        }
    };
    int n,m,l,s,dis[maxn];
    int pre[maxn],last[maxn],other[maxn],len[maxn];
    bool vis[maxn];
    priority_queue<Vergil> q;
    
    inline int read(void)
    {
        int x=0;
        char ch=getchar();
        while (ch>'9'||ch<'0') ch=getchar();
        while (ch>='0'&&ch<='9') 
        {
            x=x*10+ch-'0';
            ch=getchar();
        }
        return x;
    }
    
    void connect(int x,int y,int z)
    {
        l++;
        pre[l]=last[x];
        last[x]=l;
        other[l]=y;
        len[l]=z;
    }
    
    void update(int u,int d)
    {
        Vergil tmp;
        tmp.id=u;
        tmp.d=d;
        q.push(tmp);
    }
    
    void dijkstra(int s)
    {
        dis[s]=0;
        update(s,0);
        while (!q.empty())
        {
            Vergil tmp=q.top();q.pop();
            int u=tmp.id;
            if (vis[u]) continue;
            vis[u]=1;
            for (int p=last[u];p;p=pre[p]) 
            {
                int v=other[p];
                if (dis[v]>dis[u]+len[p]) 
                {
                    dis[v]=dis[u]+len[p];
                    update(v,dis[v]);
                }
            }
        }
    }
    
    int main()
    {
        n=read();m=read();s=read();
        for (int i=1;i<=m;i++) 
        {
            int x=read(),y=read(),z=read();
            connect(x,y,z);
        }
        for (int i=1;i<=n;i++) dis[i]=2147483647;
        dijkstra(s);
        for (int i=1;i<=n;i++) printf("%d ",dis[i]);
        return 0;
    }
    View Code

    spfa模板(容易被卡):

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #define mo 10000
    #define maxn 10010
    #define maxm 500010
    int pre[maxm],last[maxn],other[maxm],len[maxm];
    int dis[maxn],vis[maxn],que[maxn];
    int l,x,y,z,m,n,s,h,t;
    using namespace std;
    void con(int x,int y,int z)
    {
        l++;
        pre[l]=last[x];
        last[x]=l;
        other[l]=y;
        len[l]=z;
    }
    void spfa(int s)
    {
        memset(dis,0x3f,sizeof(dis));
        int h=0,t=1;
        dis[s]=0;
        que[1]=s;
        while(h!=t)
        {
            h=h%mo+1;
            int u=que[h];
            vis[u]=0;
            for(int p=last[u];p;p=pre[p])
            {
                int v=other[p];
                if(dis[v]>dis[u]+len[p])
            {
                dis[v]=dis[u]+len[p];
                if(!vis[v])
                {
                    t=t%mo+1;
                    que[t]=v;
                    vis[v]=1;
                }
            }
            }
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<=m;i++)
        {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        con(x,y,z);
        }
        spfa(s);
        for(int i=1;i<=n;i++)
        {
            if(dis[i]!=dis[0])
            printf("%d ",dis[i]);
            else printf("%d ",2147483647);
        }
        return 0;
    }
    View Code

    *最短路可以试试反着建边反着跑 

    拓扑序入度 出度 

    欧拉XX:

     无向图:

    欧拉道路: 只有两个奇度点                                         欧拉回路: 每个点都是偶度

    有向图:

    欧拉道路: 一个点入度=出度+1 一个点出度=入度+1    欧拉回路:入度=出度       //无序字母对  骑马修栅栏

    回路属于道路

    树:

    DFS序
    重心:删除这个点后树的最大儿子最小   采用一遍dfs,计算每个点的相连的最大的连通块规模,求取最大值;再在所有最大值中找出最小的,这个点就是重心。
    直径:树的两个距离最长的点

    一个点的最远路 必是直径的一点

    字典树

    最小生成树 

    树状数组

    并查集        //银河英雄传说

    *种类并查集

    *加权并查集%

    分块

    最近公共祖先

    线段树:

    基于二分的二叉树结构  用于区间统计   优化复杂度

    对于区间的修改  //借教室

    关于DP的优化    //LIS

     线段树1模板:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 100005
    typedef long long LL;
    struct tree
    {
        int l,r;
        LL sum,lazy;
    }t[maxn*4];
    int a[maxn],n,m;
    
    void build(int x,int l,int r) 
    {
        t[x].l=l;t[x].r=r;
        if (l==r) 
        {
            t[x].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(2*x,l,mid);
        build(2*x+1,mid+1,r);
        t[x].sum=t[2*x].sum+t[2*x+1].sum;
    }
    
    void update(int x) 
    {
        t[2*x].sum+=(t[2*x].r-t[2*x].l+1)*t[x].lazy;
        t[2*x+1].sum+=(t[2*x+1].r-t[2*x+1].l+1)*t[x].lazy;
        t[2*x].lazy+=t[x].lazy;
        t[2*x+1].lazy+=t[x].lazy;
        t[x].lazy=0;
    }
    
    void change(int x,int l,int r,int z) 
    {
        if (t[x].l==l&&t[x].r==r) 
        {
            t[x].sum+=(LL)(r-l+1)*z;
            t[x].lazy+=z;
            return;
        }
        if (t[x].lazy) update(x);
        int mid=(t[x].l+t[x].r)>>1;
        if (r<=mid) change(2*x,l,r,z);
        else if (l>mid) change(2*x+1,l,r,z);
        else 
        {
            change(2*x,l,mid,z);
            change(2*x+1,mid+1,r,z);
        }
        t[x].sum=t[2*x].sum+t[2*x+1].sum;
    }
    
    LL query(int x,int l,int r) 
    {
        if (t[x].l==l&&t[x].r==r) return t[x].sum;
        if (t[x].lazy) update(x);
        int mid=(t[x].l+t[x].r)>>1;
        if (r<=mid) return query(2*x,l,r);
        else if (l>mid) return query(2*x+1,l,r);
        else return query(2*x,l,mid)+query(2*x+1,mid+1,r);    
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        build(1,1,n);
        for (int i=1;i<=m;i++) 
        {
            int opt,x,y,z;
            scanf("%d%d%d",&opt,&x,&y);
            if (opt==1) 
            {
                scanf("%d",&z);
                change(1,x,y,z);
            }
            else printf("%lld
    ",query(1,x,y));
        }
        return 0;
    }
    View Code

    线段树2模板  (乘法)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 100005
    typedef long long LL;
    struct tree
    {
        int l,r;
        LL sum,lazy1,lazy2;
    }t[maxn*4];
    int n,m,a[maxn],mo;
    
    void build(int x,int l,int r)
    {
        t[x].l=l;t[x].r=r;t[x].lazy1=1;
        if (l==r) 
        {
            t[x].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(2*x,l,mid);
        build(2*x+1,mid+1,r);
        t[x].sum=(t[2*x].sum+t[2*x+1].sum)%mo;
    }
    
    void update(int x) 
    {
        LL mul=t[x].lazy1;
        LL add=t[x].lazy2;
        t[2*x].sum=(mul*t[2*x].sum%mo+add*(t[2*x].r-t[2*x].l+1)%mo)%mo;
        t[2*x+1].sum=(mul*t[2*x+1].sum%mo+add*(t[2*x+1].r-t[2*x+1].l+1)%mo)%mo;
        (t[2*x].lazy1*=mul)%=mo;
        (t[2*x+1].lazy1*=mul)%=mo;
        (t[2*x].lazy2*=mul)%=mo;
        (t[2*x+1].lazy2*=mul)%=mo;
        (t[2*x].lazy2+=add)%=mo;
        (t[2*x+1].lazy2+=add)%=mo;
        t[x].lazy1=1;
        t[x].lazy2=0;
    }
    
    void change(int x,int l,int r,int z,int o) 
    {
        if (t[x].l==l&&t[x].r==r) 
        {
            if (o==2) (t[x].sum+=(LL)z*(r-l+1))%=mo,(t[x].lazy2+=z)%=mo;
            else t[x].sum=((LL)z*t[x].sum)%mo,(t[x].lazy1*=(LL)z)%=mo,(t[x].lazy2*=(LL)z)%=mo;
            return;
        }
        if (t[x].lazy1!=1||t[x].lazy2) update(x);
        int mid=(t[x].l+t[x].r)>>1;
        if (l>mid) change(2*x+1,l,r,z,o);
        else if (r<=mid) change(2*x,l,r,z,o);
        else 
        {
            change(2*x,l,mid,z,o);
            change(2*x+1,mid+1,r,z,o);
        }
        t[x].sum=(t[2*x].sum+t[2*x+1].sum)%mo;
    }
    
    int query(int x,int l,int r) 
    {
        if (t[x].l==l&&t[x].r==r) return t[x].sum;
        if (t[x].lazy1!=1||t[x].lazy2) update(x);
        int mid=(t[x].l+t[x].r)>>1;
        if (l>mid) return query(2*x+1,l,r);
        else if (r<=mid) return query(2*x,l,r);
        else return (query(2*x,l,mid)+query(2*x+1,mid+1,r))%mo;
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&mo);
        for (int i=1;i<=n;i++) scanf("%d",a+i);
        build(1,1,n);
        for (int i=1;i<=m;i++) 
        {
            int opt,x,y,z;
            scanf("%d%d%d",&opt,&x,&y);
            if (opt!=3) scanf("%d",&z),change(1,x,y,z,opt);
            else printf("%d
    ",query(1,x,y));
        }
        return 0;
    }
    View Code

    关键在于对lazy标记的理解

     ST表模板(倍增)

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    using namespace std;
    int n,m,mx[1000010][17],l,r;
    inline int st(int l,int r)
    {
        int k=log(r-l+1)/log(2);
        return max(mx[l][k],mx[r-(1<<k)+1][k]);
    }
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=n;i++)
        cin>>mx[i][0];
        for(int j=1;j<17;j++)
        for(int i=1;i<=n;i++)
        {
        if(i+(1<<j)-1>n)continue;
        mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
        }
        for(int i=1;i<=m;i++)
        {
        cin>>l>>r;
        cout<<st(l,r)<<endl;
        }
        return 0;
        
    }
    View Code

     字符串:

    KMP

     哈希表

    存储数据  // a-b   

    桶的优化

    算法


    DP:

    Vergil:

    首先是设计状态,我们肯定是要有一个一维或多维的状态的,那么如何设计它们的意义呢,首先我们可以分析出题目中的一些重要的量,比如当前时间,选了几个,考虑到了哪里,对于这些状态我们是要以一个值来表示这些状态的最优情况,比如f[i][j][k]..=P,i,j,k表示状态,P表示那个值,我们i,j,k,P都是这些重要的量,我们应该先把这些重要的量列出,然后感觉一下如何设计状态容易转移,一般来说设计了一个好的状态剩下的事情都比较好办。

    如果这个状态不是太好,我们可以考虑优化转移,我们可以再开一个别的数组维护我们转移的信息,比如说维护最小值,或者用高级数据结构维护,或者发现状态的一些性质(单调性),这样就能更快的转移。

    其实动态规划也是考虑了所有的状态,如果说你设计的DP没有将所有的状态考虑到,那么一定是错误的,动态规划的实质就是枚举了所有的状态,然后保留最大值。

    个人认为动态规划就是一个分类,动态规划的状态就是分类的标准,动态规划在每一中类别中都取得最优解,另外对于每个基本元素来说,一般都有几个状态,比如说背包问题中每个物品的选与不选,或者是这个元素放在哪个位置等等等等,考虑到每个元素的状态也有助于我们设计整体的状态。

    区间DP:

    由小到大         //合并石子

    背包DP:

    背包九讲

    https://www.cnblogs.com/jbelial/articles/2116074.html

    选与不选         //津津的储蓄计划

    树形DP:

    树形背包      //选课

    选择结点      //没有上司的舞会

    状压DP:

    用二进制串进行选与不选    //炮兵阵地   互不侵犯king

    贪心(玄学)

    1.数学式子推出结论

    2.考虑临界   感受贪心策略可不可行(用心去感受~)

    二分:

    *最大的最小值

    二分需具有单调性

    如果是单峰函数 则需三分 //借教室  期末考试 通向奥格瑞玛的道路

    三分:期末考试代码

     
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 100005
    typedef long long LL;
    LL A,B,C,ans;
    int t[maxn],b[maxn],n,m,L,R;
     
    LL f(int x)
    {
        LL res1=0;
        LL res2=0;
        LL ff=0;
        for (int i=1;i<=m;i++) 
            if (b[i]<x) res1+=(x-b[i]);
        for (int i=1;i<=m;i++)
            if (b[i]>x) res2+=(b[i]-x);
        if (A>=B) ff=res2*B;
        else
        {
            if (res1>=res2) ff=res2*A;
            else
            {
                ff=res1*A;
                res2-=res1;
                ff+=res2*B;
            }
        }
        for (int i=1;i<=n;i++) 
            if (t[i]<x) ff+=C*(x-t[i]);
        return ff;
    }
     
    int main()
    {
        scanf("%lld%lld%lld",&A,&B,&C);
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&t[i]);
        for (int i=1;i<=m;i++) scanf("%d",&b[i]),R=max(R,b[i]);
        if (C>1e6+1) 
        {
            int x=1e5+1;
            for (int i=1;i<=n;i++) x=min(x,t[i]);
            printf("%lld
    ",f(x));
            return 0;
        }
        L=1;ans=1e18;
        while (R-L>=5) 
        {
            int mid1=(L+R)>>1;
            int mid2=(mid1+R)>>1;
            LL ans1=f(mid1);
            LL ans2=f(mid2);
            if (ans1<ans2) 
            {
                ans=min(ans,ans1);
                R=mid2;
            }
            else
            {
                ans=min(ans,ans2);
                L=mid1;
            }
        }
        for (int i=L;i<=R;i++) 
            ans=min(ans,f(i));
        printf("%lld
    ",ans);
        return 0;
    }
    View Code

    差分:

    同样用于优化复杂度

    往往是多次修改单次查询

    开一个差分数组维护影响     //luogu3397 地毯

     数学:


    矩阵快速幂:   //斐波那契数列

    欧拉筛素数

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int n,m;
    int i,j;
    bool flag[10000010];
    int p[1000010];
    int tot,x;
    int main()
    {
        cin>>n>>m;
        flag[1]=1;
        for(int i=2;i<=n;i++)
        {
            if(flag[i]==0)
            {
            tot++;
            p[tot]=i;
             }
        for(int j=1;j<=tot;j++)
        {
            if(p[j]*i>n) break;
            flag[p[j]*i]=1;
            if(i%p[j]==0) break;
        }
       }
       for(int i=1;i<=m;i++)
       {
           cin>>x;
           if(flag[x]==0) cout<<"Yes"<<endl;
           else cout<<"No"<<endl; 
       }
       return 0;
       
    }
    View Code

    需要加强的地方:

    DP写不好转移方程

    线段树不会应用

    STL使用不熟练

    做题时不能看出要用哪个算法

    代码能力差

  • 相关阅读:
    C#中的WebBrowser控件的使用
    xshell5 可用注册码
    一次多数据源 配置问题记录
    org.springframework.data.mongodb.core.MongoTemplate]: Constructor threw exception; nested exception is java.lang.NoSuchMethodError: org.springframework.core.convert.support.ConversionServiceFactory.cr
    关于 <mvc:argument-resolvers> 的一次使用记录
    补码、反码、原码 ~ ^ 运算
    mysql中int、bigint、smallint 和 tinyint的区别与长度的含义【转】
    tomcat优化记录
    判读40亿数字中是否有某个数字
    LinkedList源码疑问记录
  • 原文地址:https://www.cnblogs.com/637w/p/10333904.html
Copyright © 2011-2022 走看看