A. Make Even
题意:
给你一个数字,你可以任意反转他的前缀,问最少反转几次可以使得这个数为偶数
分析:
首先很明显的是,如果给的数中每一位都是奇数那么很明显不可能
- 刚开始就是偶数答案为0
- 最高位为偶数答案为1
- 其次答案为2
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
int num;cin>>num;
if (num%2==0)
{
cout<<"0\n";
continue;
}vector<int> ns;
int cnt=0;
while (num)
{
ns.push_back(num%10);
if (num%10%2==0)++cnt;
num/=10;
}
if (cnt==0)
{
cout<<"-1\n";
continue;
}
if (ns.back()%2==0)
{
cout<<"1\n";
continue;
}
cout<<"2\n";
}
}
B. Team Composition: Programmers and Mathematicians
题意:
有aaa个数学家,bbb个工程师,要求组最多的444人队伍,要求每个队伍至少有一名数学家和一名工程师
分析:
如果a=ba=ba=b,那么我们肯定两个数学家两个工程师这样组队
如果不相等的话,那么我们肯定先让人多派三个人,人少的派一个人。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
int n,m;cin>>n>>m;
if (n<m)swap(n,m);
int cnt = min({n/3,m,(n-m)/2});
n -= 3*cnt;
m -= cnt;
cout<<cnt+min(n/2,m/2)<<"\n";
}
}
C. Polycarp Recovers the Permutation
题意:
一个长为nnn的排列,每次对比两端数字的大小,取小的数字
- 小的数字是左端的,则放入新排列的左端
- 小的数字是右端的,则放入新排列的右端
如此,构成了一个新排列
现在给你一个新排列,要求你构造出老排列
分析:
很明显的一个结论是,最大的那个数nnn一定在新排列的最左端过着最右端
因为,他是最大的,一定是最后被放入的
然后我们可以这样构造老排列,先在新排列找到最大的数nnn,然后翻转其他的数
就是老排列了
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
int a[maxn];
int n;
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
cin>>n;
for (int i=1;i<=n;++i)cin>>a[i];
if (a[1]==n)reverse(a+2,a+1+n);
else if (a[n]==n)reverse(a+1,a+n);
else
{
cout<<"-1\n";
continue;
}
for (int i=1;i<=n;++i)cout<<a[i]<<" ";cout<<endl;
}
}
D. Weights Assignment For Tree Edges
题意:
给你一棵树,请你给边分配权值>0>0>0。
要求,将所有点按照到达根节点的距离排序大的排列,要符合题目给的排列
分析:
一个节点到达根节点的距离,一定是大于他的父亲节点到达根节点的距离
因此,所给排列ppp中,p[i]p[i]p[i]的父节点一定在iii之前出现过了
因此,我们可以暴力的给边赋值
具体是,遍历到p[i]p[i]p[i],然后查看他的父节点fa[p[i]]fa[p[i]]fa[p[i]]
- fa[p[i]]fa[p[i]]fa[p[i]]未被遍历到,返回−1-1−1
- p[i]p[i]p[i]到达他父亲节点的边长为max(1,dist[p[i−1]]−dist[fa[p[i]]]+1)\max(1, dist[p[i-1]]-dist[fa[p[i]]] +1)max(1,dist[p[i−1]]−dist[fa[p[i]]]+1)
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+100;
int b[maxn],p[maxn],vis[maxn];
ll dis[maxn],res[maxn];
int n;
void solve()
{
cin>>n;
for (int i=1;i<=n;++i)
{
cin>>b[i];
vis[i]=1;
if (i==b[i])vis[i]=0;
}
for (int i=1;i<=n;++i)cin>>p[i];
if (b[p[1]]!=p[1])
{
cout<<"-1\n";
return;
}dis[p[1]]=res[p[1]]=0;
for (int i=2;i<=n;++i)
{
if (vis[b[p[i]]])
{
cout<<"-1\n";
return;
}
res[p[i]]=max(1LL, dis[p[i-1]] - dis[b[p[i]]]+1);
dis[p[i]] = dis[b[p[i]]]+res[p[i]];
vis[p[i]]=0;
}
for (int i=1;i<=n;++i)cout<<res[i]<<" ";cout<<endl;
}
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
solve();
}
}
E1. Escape The Maze (easy version)
题意:
给一棵树,VladVladVlad在根节点,他的目标是走到一处叶子节点
VladVladVlad的kkk个朋友站在其他的一些点上,目的是拦下VladVladVlad,他们每次只能走一下,
VladVladVlad先手,问VladVladVlad能否走到一处叶子节点
分析:
从朋友角度,我们可以发现,因为树的特殊性,朋友一定是不断向父节点走的!
每到达一处父节点,那么就可以覆盖掉该父节点代表的子树下的所有叶子节点!
$Vlad $选择一处叶子节点为目标,朋友们不断向父节点走,如果能提前走到根到叶子节点唯一路径上,
那么就被成功阻止了。
而,组织了VladVladVlad的朋友,最远也只能走到自己原来节点深度的121\over 221
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
vector<int> G[maxn];
int dep[maxn],fa[maxn][20];
int vis[maxn],x[maxn];
int n,k;
void dfs(int u,int p)
{
fa[u][0]=p;dep[u]=dep[p]+1;
for (int v:G[u])if (v!=p)
dfs(v,u);
}
bool dfs2(int u)
{
if (G[u].size()==1&&u!=1)return true;
for (int v:G[u])if (v!=fa[u][0]&&!vis[v]&&dfs2(v))return true;
return false;
}
void solve()
{
cin>>n>>k;
for(int i=1;i<=k;++i)cin>>x[i];
for (int i=1;i<=n;++i)G[i].clear(),vis[i]=0;
for (int i=1,u,v;i<n;++i)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}dfs(1,0);
for (int k=1;k<20;++k)
for (int i=1;i<=n;++i)fa[i][k] = fa[fa[i][k-1]][k-1];
for (int i=1;i<=k;++i)
{
int xi = x[i];
for (int k = 19;k>=0;--k)
if (dep[fa[xi][k]]*2>dep[x[i]])xi = fa[xi][k];
vis[xi]=1;
}
if(dfs2(1))
{
cout<<"Yes\n";
}else cout<<"No\n";
}
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
solve();
}
}
E2. Escape The Maze (hard version)
题意:
和E1E1E1一样,不同的是问最少需要保留多少朋友才能成功阻止$Vlad $
分析:
基本思路和E1E1E1一样,每个朋友都尽可能地向上走,去阻止。
因此,我们在第二次dfsdfsdfs遍历时,只需要统计被几个朋友挡回来就可以了
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+100;
vector<int> G[maxn];
int dep[maxn],fa[maxn][20];
int vis[maxn],x[maxn];
int n,k;
void dfs(int u,int p)
{
fa[u][0]=p;dep[u]=dep[p]+1;
for (int v:G[u])if (v!=p)
dfs(v,u);
}
int ans = 0;
bool dfs2(int u)
{
if (vis[u])
{
++ans;
return false;
}
if (G[u].size()==1&&u!=1)return true;
for (int v:G[u])if (v!=fa[u][0])
if (dfs2(v))return true;
return false;
}
void solve()
{
cin>>n>>k;
for(int i=1;i<=k;++i)cin>>x[i];
for (int i=1;i<=n;++i)G[i].clear(),vis[i]=0;
for (int i=1,u,v;i<n;++i)
{
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}dfs(1,0);
for (int k=1;k<20;++k)
for (int i=1;i<=n;++i)fa[i][k] = fa[fa[i][k-1]][k-1];
for (int i=1;i<=k;++i)
{
int xi = x[i];
for (int k = 19;k>=0;--k)
if (dep[fa[xi][k]]*2>dep[x[i]])xi = fa[xi][k];
vis[xi]=1;
}
ans = 0;
if(!dfs2(1))
{
cout<<ans<<"\n";
}else cout<<"-1\n";
}
int main()
{
ios::sync_with_stdio(0);
int T;cin>>T;
while (T--)
{
solve();
}
}
F. ATM and Students
题意:
求出一个最长连续子序列保证其中所有的前缀和不小于kkk
分析:
双指针对数组a求最大连续子序列和
对某一段(l,r)(l,r)(l,r)区间满足答案要求,则更新答案,跳右指针。
若跳完右指针不满足条件,则不断跳lll直到满足条件。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int t,n,m,k,l,r,ansl,ansr,sum,s;
int a[200005];
void init(){
ansl=ansr=-1,sum=0,l=r=1;
}
void update(){
if(r-l>ansr-ansl) ansr=r,ansl=l;
}
void solve(){
cin>>n>>s;
for(int i=1;i<=n;i++)cin>>a[i];
init();
while(l<=n&&r<=n+1){
if(sum+s>=0)update(),sum+=a[r++];
else sum-=a[l++];
}
if(ansr==-1) cout<<-1<<endl;
else cout<<ansl<<" "<<ansr-1<<endl;
}
signed main(){
cin>>t;
while(t--)
solve();
}
int t,n,m,k,l,r,ansl,ansr,sum,s;
int a[200005];
void init(){
ansl=ansr=-1,sum=0,l=r=1;
}
void update(){
if(r-l>ansr-ansl) ansr=r,ansl=l;
}
void solve(){
cin>>n>>s;
for(int i=1;i<=n;i++)cin>>a[i];
init();
while(l<=n&&r<=n+1){
if(sum+s>=0)update(),sum+=a[r++];
else sum-=a[l++];
}
if(ansr==-1) cout<<-1<<endl;
else cout<<ansl<<" "<<ansr-1<<endl;
}
signed main(){
cin>>t;
while(t–)
solve();
}
这篇博客详细解析了Codeforces Round #756 (Div. 3)的比赛题目,包括A. Make Even、B. Team Composition、C. Polycarp Recovers the Permutation等,涉及数论、图论和动态规划等多个知识点,适合ACM竞赛选手和编程爱好者学习。
693

被折叠的 条评论
为什么被折叠?



