2022/7/22 训练日志

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2022/7/22 训练日志相关的知识,希望对你有一定的参考价值。

思维训练

D1. Chopping Carrots (Easy Version)

题意:给定一个数组a[n],构造一个数组p[n],使得Max(a[i]/p[i])-Min(a[i]/p[i])值最大。n的数据范围到3000.要求算式答案最小。
思路:
1.首先最容易想到要确定p数组的值,但这思路并不正确,首先会导致复杂度过大。
2.仔细观察算式,相除最大值无法确定,但最小值确存在范围1~a[1] (数组大小为升序排列)
3.若枚举最小值后,下一步确定最大值,p[i]的值存在限制,必须要<=k,再比较找出一个算式答案最小。

#include <bits/stdc++.h>
//#define int long long
#define endl '\\n'

using namespace std;
const int N=1e6+100;
int n,k,a[N];
signed main()

    int t;cin>>t;
    while(t--)
    
        cin>>n>>k;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int ans=1e9,g=a[1];
        for(int i=1;i<=g;i++)
        
            int res=0;
            for(int j=1;j<=n;j++)
            
                int x=a[j]/i;
                if(x>k) x=k;
                res=max(res,a[j]/x);
            
            ans=min(ans,res-i);
        
        cout<<ans<<endl;
    
    return 0;



C1. k-LCM (easy version)

本题为C2的简化版,k恒等于3。因此表明要围绕n/2进行分类讨论。

#include <bits/stdc++.h>
//#define int long long
#define endl '\\n'

using namespace std;
const int N=1e6+100;
int n,k;
signed main()

    int t;cin>>t;
    while(t--)
    
        cin>>n>>k;
        int g=n/2;
        if(n%2)
            cout<<1<<" "<<g<<" "<<g<<endl;
        else
        
            if(g%2)
                cout<<2<<" "<<g-1<<" "<<g-1<<endl;
            else
                cout<<g<<" "<<g/2<<" "<<g/2<<endl;
        

    
    return 0;

每日一题

C2. k-LCM (hard version)

在C1的基础上,将输出k-3个1,再将n-=(k-3),此时有三个数来构成n,题目便变化成了C1

#include <bits/stdc++.h>
//#define int long long
#define endl '\\n'

using namespace std;
const int N=1e6+100;
int n,k;
signed main()

    int t;cin>>t;
    while(t--)
    
        cin>>n>>k;
        for(int i=1;i<=k-3;i++)
            cout<<1<<" ";
        n-=(k-3);
        int g=n/2;
        if(n%2)
            cout<<1<<" "<<g<<" "<<g<<endl;
        else
        
            if(g%2)
                cout<<2<<" "<<g-1<<" "<<g-1<<endl;
            else
                cout<<g<<" "<<g/2<<" "<<g/2<<endl;
        

    
    return 0;



算法训练

P1137 旅行计划

一道经典得拓扑排序题,
思路:
1.一张有向无环图的拓扑序可以使得任意的起点u,它的一个终点v,在序列中的顺序是u在前v在后
2.把入度为0的点入队,并加入拓扑序。之后断掉以这个点为起点的边,即将这些边的终点的入度减一,直到队为空就好。

#include <bits/stdc++.h>

using namespace std;
const int maxn=2e5+5;
int n,m,indgr[maxn],city[maxn],head[maxn],cnt;
struct node

    int to,nxt;
g[maxn];
queue<int>q;
void add_edge(int u,int v)

    g[++cnt].to=v;
    g[cnt].nxt=head[u];
    head[u]=cnt;

void topsort()

    for(int i=1;i<=n;i++)
    
       if(indgr[i]==0)
       
           city[i]=1;q.push(i);
       
    
    while(!q.empty())
    
        int k=q.front(); //取得入度为0的结点
        q.pop();
        for(int i=head[k];i;i=g[i].nxt) //i表示与邻接点相连的变
        
            int v=g[i].to; //通过这个点找到的下一个点
            indgr[v]--;   //入度减去1
            city[v]=max(city[v],city[k]+1);  //dp思想
            if(indgr[v]==0)  //若为0加入队列
            
                q.push(v);
            
        
    

int main()

    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    
        head[i]=-1;city[i]=1;
    
    for(int i=1;i<=m;i++)
    
        int a,b;
        scanf("%d%d",&a,&b);
        add_edge(a,b);
        indgr[b]++;
    
    topsort();
    for(int i=1;i<=n;i++)
    
        cout<<city[i]<<endl;
    
    return 0;

E. Qpwoeirut and Vertices

本题涉及知识较多,尚有ST表部分的应用没看懂,得抽个时间将ST表内容学下。

#include <bits/stdc++.h>
//#define int long long
#define endl '\\n'

using namespace std;
const int N=1e5+100;
int n,m,f[N],tol,val[N],lg[N];
vector<int>g[N];
bool vis[N];
//并查集模板
int r_find(int r)

    if(r==f[r])    return f[r];
    f[r]=r_find(f[r]);
    return f[r];

//树链剖分模板
int son[N],siz[N],top[N],fa[N],dep[N];
void dfs1(int u,int pare)   //重构树lca初始化

    siz[u]=1;dep[u]=dep[pare]+1;
    son[u]=0;fa[u]=pare;
    for(auto &v:g[u])
    
        if(v!=pare)
        
            dfs1(v,u);
            siz[u]+=siz[v];
            if(siz[son[u]]<siz[v])
                son[u]=v;
        
    

void dfs2(int u,int topf)

    top[u]=topf;
    if(son[u])
        dfs2(son[u],topf);
    for(auto &v:g[u])
    
        if(v!=fa[u]&&v!=son[u])
            dfs2(v,v);
    

//树剖求lca模板
int lca(int x,int y)

    while(top[x]!=top[y])
    
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    
    return dep[x]<dep[y]?x:y;

//kurskral重构树模板
void kruskal()

    for(int i=1;i<n*2;i++)
        f[i]=i;
    tol=n;
    for(int i=1;i<=m;i++)
    
        int x,y;cin>>x>>y;
        int fx=r_find(x),fy=r_find(y);
        if(fx!=fy)
        
            val[++tol]=i;
            f[fx]=f[fy]=tol;
            g[fx].push_back(tol),g[tol].push_back(fx);
            g[fy].push_back(tol),g[tol].push_back(fy);
        
    


//ST表求区间最大值
void build()



//ST表查询区间极大值
void query()



signed main()

    int t;cin>>t;
    for(int i=1;i<=N;i++)
        lg[i]=lg[i>>1]+1;
    while(t--)
    
        cin>>n>>m;
        kruskal();
        dfs1(tol,0);
        dfs2(tol,tol);
        int q;cin>>q;
        while(q--)
        
            int l,r;cin>>l>>r;

        
        for(int i=1;i<=tol;i++)
            g[i].clear(),sz[i]=top[i]=fa[i]=son[i]=dep[i]=0;
    
    return 0;



以上是关于2022/7/22 训练日志的主要内容,如果未能解决你的问题,请参考以下文章

算法训练——最大的算式

蓝桥杯 算法训练 ALGO-116 最大的算式

算法训练 简单加法(基本型)

算法训练 最大的算式(DP)

3星难度-算式填符号

2022-7-22 面经复习+简单题目整理