开学二周(日常补题训练)
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补题
题解:首先大体思想就是把每一个桥的最少费用算出来
然后我们写一个前缀和,不断枚举取最小的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; }