总体总结
A,B题纯模拟
C题 公式一步转换
D题 五题里面最难的,dp预处理+二分
E题 排序+BFS
题解
A题 A Substring
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int a,b;
string s;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>a>>b;
cin>>s;
for(int i=a;i<n-b;i++)
{
cout<<s[i];
}
cout<<endl;
return 0;
}
B题 Search and Delete
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+10;
typedef long long ll;
int t,n,m;
int a[N];
int b[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=0;i<n;i++)cin>>a[i];
for(int i=0;i<m;i++)cin>>b[i];
sort(b,b+m);
int cnt=0;
for(int i=0;i<n;i++)
{
if(a[i]==b[cnt])a[i]=0,cnt++;
else
{
while(cnt<m&&a[i]>b[cnt])cnt++;
if(cnt<m&&a[i]==b[cnt])a[i]=0,cnt++;
}
if(cnt==m)break;
}
for(int i=0;i<n;i++)
{
if(a[i]!=0)cout<<a[i]<<' ';
}
return 0;
}
C题 Distance Indicators
\[j-i = A_i+A_j $$$$ j-A_j = i+A_i \]
#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int t,n;
int a[N];
int cnt[2*N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
ll ans=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
int x = i - a[i];
if(x>=1&&cnt[x])ans+=cnt[x];
cnt[i+a[i]]++;
}
cout<<ans<<endl;
return 0;
}
D题 Takahashi's Expectation
首先dp预处理,dp[i][j]表示在第i个礼品时候的心情为j时,最后的心情是多少
然后用lower_bound(),求出什么时候mood小于前缀和presum,然后根据求出的位置,进行计算,如果求出,位置在结尾之后,说明一开始的心情过高,最后答案就是mood-presum[n]
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10;
typedef long long ll;
int t,n;
int p[N],a[N],b[N];
int presum[N];
int dp[N][1001];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>p[i]>>a[i]>>b[i];
presum[i]=presum[i-1]+b[i];
}
for(int i=0;i<=1000;i++)dp[n+1][i]=i;
for(int i=n;i>=1;i--)
{
for(int j=0;j<=1000;j++)
{
if(j>p[i])
{
dp[i][j]=dp[i+1][max(0,j-b[i])];
}
else
{
dp[i][j]=dp[i+1][j+a[i]];
}
}
}
int q;
cin>>q;
while(q--)
{
int x;
cin>>x;
int mid = lower_bound(presum+1,presum+n+1,x-500)-presum;
if(mid==n+1)
{
cout<<x-presum[n]<<endl;
}
else
{
cout<<dp[mid][x-presum[mid-1]]<<endl;
}
}
return 0;
}
E题 A Path in A Dictionary
每次先把所有节点的边进行从小到大排序,然后bfs遍历每一个点,时间复杂度为O(n),求出字典序最小的路径
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int m,x,y;
bool flag = false;
bool vis[1001];
vector<ll>res;
vector<ll>graph[1001];
void dfs(int cur)
{
if(flag)return;
if(cur==y)
{
for(int i=0;i<res.size();i++)cout<<res[i]<<' ';
cout<<endl;
flag = true;
return ;
}
for(auto it:graph[cur])
{
if(vis[it])continue;
res.push_back(it);
vis[it]=true;
dfs(it);
res.pop_back();
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
flag =false;
memset(vis,false,sizeof(vis));
cin>>n>>m>>x>>y;
for(int i=1;i<=1000;i++)graph[i].clear();
for(int i=1;i<=m;i++)
{
int f,t;
cin>>f>>t;
graph[f].push_back(t);
graph[t].push_back(f);
}
for(int i=1;i<=n;i++)sort(graph[i].begin(),graph[i].end());
vis[x]=true;
res.push_back(x);
dfs(x);
res.clear();
}
return 0;
}