Codeforces Round #756 (Div. 3)
A. Make Even
分析:
- 就 0 , 1 , 2 , − 1 0,1,2,-1 0,1,2,−1 四种情况
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
char s[N];
signed main()
{
int T;
cin>>T;
while(T--)
{
cin>>s+1;
int n=strlen(s+1);
int ans=0,fg=0;
if((s[n]&1)==0) cout<<"0\n";
else
{
if((s[1]&1)==0) cout<<"1\n"; // 头为偶数
else
{
for(int i=1;i<=n;i++)
{
if((s[i]&1)==0)
{
fg=1; break;
}
}
if(fg) cout<<"2\n"; //中间有偶数,先将偶数反转到第一位,再从头到尾,2步
else cout<<"-1\n";
}
}
}
}
B. Team Composition: Programmers and Mathematicians
- 小学数学
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
char s[N];
signed main()
{
int T;
cin>>T;
while(T--)
{
int a,b;
cin>>a>>b;
if(a>b) swap(a,b);
cout<<min(a,(a+b)/4)<<endl;
}
}
C. Polycarp Recovers the Permutation
分析:
-
构造题
-
首先,最大的数在新数组中一定是第 1 个或第 n 个(即头或尾)
-
假设在原数组中,最大的在左端,那么构造新数组时,就是原数组的倒置
所以,将新数组倒置就是原数组
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N],p[N];
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
if(a[1]==n || a[n]==n)
{
for(int i=n;i>=1;i--) cout<<a[i]<<' ';
cout<<"\n";
}
else cout<<"-1\n";
}
signed main()
{
ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--) solve();
}
D. Weights Assignment For Tree Edges
分析:
-
构造题
-
要使 n 条边权的大小按一定顺序(根为0),从 1 到 n 按顺序赋值给 n 个点即可
最后要输出的 ans 即,当前点的点权 - 其父亲点权 = 该点边权
-
-1 的情况,就是按顺序轮到某一点,但是其父亲还未被赋值,即:根越过父亲直接到儿子了,显然不成立
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N],p[N];
int ans[N];
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i], ans[i]=0;
for(int i=1;i<=n;i++) cin>>p[i];
if(p[1]!=a[p[1]]) cout<<"-1\n";
else
{
ans[p[1]]=1;
for(int i=2;i<=n;i++)
{
if(!ans[a[p[i]]])
{
cout<<"-1\n";
return ;
}
ans[p[i]]=i;
}
for(int i=1;i<=n;i++) cout<<ans[i]-ans[a[i]]<<' ';
cout<<"\n";
}
}
signed main()
{
ios_base::sync_with_stdio(0);
int T;
cin>>T;
while(T--) solve();
}
E1. Escape The Maze (easy version)
分析:
-
多源点同时覆盖
-
所有 x i x_i xi (还有 根1)同时向四面八方覆盖
若最后 根1 能到达某一个叶子节点,输出 “YES” 即可
-
注意:
if(pr[u]==1 && g[u].size()==1 && u!=1) 中的 u!=1 不要忘记
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int x[N];
vector <int> g[N];
int n,k;
int vis[N],pr[N]; // pr存从哪一点出发
bool bfs()
{
queue <int> q;
for(int i=1;i<=k;i++)
{
vis[x[i]]=1;
q.push(x[i]);
}
q.push(1); // 这个一定要在所有 xi 入队之后再入队,不然由于 ”时间差“ 会错
vis[1]=1;
pr[1]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
if(pr[u]==1 && g[u].size()==1 && u!=1) // 从 1 成功到达某一个叶子
{
return 1;
}
for(int v : g[u])
{
if(!vis[v])
{
vis[v]=1;
q.push(v);
pr[v]=pr[u];
}
}
}
return 0;
}
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++) vis[i]=pr[i]=0, g[i].clear();
for(int i=1;i<=k;i++) cin>>x[i];
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
if(bfs()) cout<<"YES\n";
else cout<<"NO\n";
}
signed main()
{
ios_base::sync_with_stdio(0);
int T;
cin>>T;
while(T--) solve();
}
E2. Escape The Maze (hard version)
分析
-
同上题的区别:让统计最少需要多少人
-
只需考虑 根1 在覆盖过程中能遇到的点即可,放在 set 再去重,返回 size 即可
-
注意:
if(pr[u]==1 && pr[v]!=1) se.insert(pr[v]); 不要少了 pr[v]!=1
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int x[N];
vector <int> g[N];
int n,k;
int vis[N],pr[N];
set <int> se;
int bfs()
{
queue <int> q;
for(int i=1;i<=k;i++)
{
vis[x[i]]=1;
q.push(x[i]);
pr[x[i]]=x[i];
}
q.push(1);
vis[1]=1;
pr[1]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
if(pr[u]==1 && g[u].size()==1 && u!=1)
{
return -1;
}
for(int v : g[u])
{
if(!vis[v])
{
vis[v]=1;
q.push(v);
pr[v]=pr[u];
}
else
{
if(pr[u]==1 && pr[v]!=1) se.insert(pr[v]); // 注意点
}
}
}
return se.size();
}
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++) vis[i]=pr[i]=0, g[i].clear();
se.clear();
for(int i=1;i<=k;i++) cin>>x[i];
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
int ans=bfs();
cout<<ans<<"\n";
}
signed main()
{
ios_base::sync_with_stdio(0);
int T;
cin>>T;
while(T--) solve();
}
F. ATM and Students
分析:
- 双指针板子题
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int a[N];
int n,k;
void solve()
{
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i];
int l=1,r=0,ans=0,t=k,anl,anr;
while(l<=n && r<=n)
{
if(t>=0)
{
if(r-l+1>ans)
{
ans=r-l+1;
anl=l; anr=r;
}
t+=a[++r];
}
else
{
t-=a[l++];
}
}
if(ans>0) cout<<anl<<' '<<anr<<"\n";
else cout<<"-1\n";
}
signed main()
{
ios_base::sync_with_stdio(0);
int T;
cin>>T;
while(T--) solve();
}