开学二周(日常补题训练)

pta天梯专栏

7-11 龙龙送外卖 - SMU 2024 spring 天梯赛1(补题) (pintia.cn)

题解:首先我们先建个图然后存一下各个节点的父亲节点

我们细看这个最短路可以发现,当全部节点加进来,那么最短路就是每一个节点跑两遍然后最深的那个节点最后才跑,这样就只需要1遍

所以我们首先把每一个节点的深度算出来,然后分别记录

然后我们一个个把需要用到的点加进来,从这个节点向上跑到根节点或者跑到之前跑过的点记录答案即可,

如果这点跑过,直接输出答案即可ans-ma+1

ma是最大的深度

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=1e5+9,M=1e1;
const int INF = 0x3f3f3f3f;
const int mod=1e9+7;
typedef pair<int,int> PII;
int kmp(int a,int k,int p)
{
    int ans=1;
    while (k)
    {
        if(k&1) ans=ans*a%p;
        k>>=1;
        a=a*a;
    }
    return ans;
}

vector<int> a[N];
int fa[N];
int dep[N];
bool st[N];
int ans;
int root=0;
void dfs1(int u,int de)
{
    dep[u]=de;
    for(auto i:a[u])
    {
        dfs1(i,de+1);
    }
}
void dfs2(int u)
{
    if(st[u] || u==root) return;
    st[u]= true;
    ans+=2;
    dfs2(fa[u]);
}
void solve()
{
    int n,m;
    cin>>n>>m;

    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        if(x==-1)
        {
            root=i;
            fa[i]=i;
        }
        else
        {
            a[x].push_back(i);
            fa[i]=x;
        }
    }
    dfs1(root,1);
    int ma=-1;
    while (m--)
    {
        int x;
        cin>>x;
        if(st[x]) cout<<ans-ma+1<<endl;
        else
        {
            ma=max(ma,dep[x]);
            dfs2(x);
            cout<<ans-ma+1<<endl;
        }
    }
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 CF补题

Problem - E - Codeforces

题解:首先大体思想就是把每一个桥的最少费用算出来

然后我们写一个前缀和,不断枚举取最小的k连续子段即可

现在我们来想想每一条路径最少费用怎么写

我想到dp滑动窗口优化

一个双向队列

每次放入一个点

然后两柱子距离超过k那么前一柱子就弹出

状态转移就是dp[j]=dp[q.front]+a[i][j]+1      这样就是距离最远的一个点最优值

然后我们还要对队列尾巴跑一个while,把花费大的弹出

#include <bits/stdc++.h>
//#pragma GCC optimize("Ofast")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
//#define double long double
#define int long long
#define endl '\n'
using namespace std;
const int N=2e5+5,M=1e9+7;
const int INF = 0x3f3f3f3f;
const int mod=998244353;
typedef pair<int,int> PII;

int a[105][N];
void solve()
{
    int n,m,k,d;
    cin>>n>>m>>k>>d;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>a[i][j];
        }
    }
    vector<int> sum;
    for(int i=1;i<=n;i++)
    {
        deque<int> q;
        int dp[m+2];
        dp[1]=1;
        q.push_back(1);
        for(int j=2;j<=m;j++)
        {
            while (!q.empty() && j-q.front()-1>d) q.pop_front();
            dp[j]=dp[q.front()]+a[i][j]+1;
            while (!q.empty() && dp[q.back()]>dp[j]) {
                q.pop_back();
            }
            q.push_back(j);
        }
        sum.push_back(dp[m]);
    }
    int pp[N];
    pp[0]=sum[0];
    for(int i=1;i<sum.size();i++)
    {
        pp[i]=pp[i-1]+sum[i];
    }
    int ans=pp[k-1];
    for(int i=k;i<sum.size();i++)
    {
        ans=min(ans,pp[i]-pp[i-k]);
    }
    cout<<ans<<endl;
}
signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int T=1;
    cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

 

posted @ 2024-03-12 17:46  whatdo+  阅读(4)  评论(0编辑  收藏  举报