Codeforces Round 1065 (Div. 3)(A-D,F)
A. Shizuku Hoshikawa and Farm Legs
题目链接:Problem - A - Codeforces
思路:
一个简单的鸡兔同笼问题,就是要注意动物的数量可以取到0;
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n;cin>>n;
int ans=0;
for(int i=0;i<=n/4;i++){
if((n-i*4)%2==0) ans++;
}
cout<<ans<<"\n";
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
B. Yuu Koito and Minimum Absolute Sum
题目链接:Problem - B - Codeforces
思路:
首先,通过观察我们可以发现,中间所有的-1项对于结果不产生影响(a[i]-a[i-1]+a[i+1]-a[i]==a[i+1]-a[i]),所以中间的-1全部都设置成0(因为要字典序最小);
因此,只需要特殊处理第一项和最后一项是-1的情况:
- 先处理如果第一项为-1(因为要字典序最小):
- 如果最后一项也为-1:直接无脑填0就好,让绝对值最小的任务可以直接交给最后一项QWQ
- 否则,a[1]=max(0,a[2]-s[n]);
- 如果最后一项为-1
- a[n]=max(0,a[n-1]+s[n]);
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+12;
int a[N],s[N];
void solve(){
int n;cin>>n;
for(int i=1;i<=n;i++){
a[i]=0;s[i]=0;
}
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
if(a[i]==-1){
if(i!=1&&i!=n) a[i]=0;
}
}
if(n==2&&a[1]==-1&&a[2]==-1){
cout<<"0\n"<<"0 0\n";return ;
}
for(int i=2;i<=n;i++){
if(a[i]!=-1&&a[i-1]!=-1){
s[i]=s[i-1]+(a[i]-a[i-1]);
}
else s[i]=s[i-1];
}
if(a[1]==-1&&a[n]==-1){
a[1]=0;
s[n]=s[n]+(a[2]-a[1]);
}
else if(a[1]==-1){
a[1]=max(0LL,a[2]+s[n]);
s[n]=s[n]+(a[2]-a[1]);
}
if(a[n]==-1){
a[n]=max(0LL,(a[n-1]-s[n]));
s[n]=s[n]+(a[n]-a[n-1]);
}
cout<<abs(s[n])<<"\n";
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}cout<<"\n";
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
/*
1 3 -1 2 0
*/
C1. Renako Amaori and XOR Game (easy version)
题目链接:Problem - C1 - Codeforces
思路:
前置知识:0a=a;1a=~a;
因为0≤ai,bi≤1,所以两个人最后的结果只能是0或者1,其中:
- 有奇数个1答案为1;
- 有偶数个1答案为0;
贪心的去想,对于二人来说,只要在自己可移动的位数上且自己此时正好有偶数个1,则一定选择交换。
最终比较两人手中1的奇偶性即可;
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+12;
int a[N],b[N];
void solve(){
int n;cin>>n;
int a1=0,b1=0;
for(int i=1;i<=n;i++){
cin>>a[i];if(a[i]==1) a1++;
}
for(int i=1;i<=n;i++){
cin>>b[i];if(b[i]==1) b1++;
}
for(int i=1;i<=n;i++){
if(a[i]==b[i]) continue;
if(i%2==1&&a1%2==0){
if(a[i]==0){
a1++;b1--;
}else{
a1--;b1++;
}
}
if(i%2==0&&b1%2==0){
if(b[i]==0){
b1++;a1--;
}else{
b1--;a1++;
}
}
}
if(a1%2==b1%2){
cout<<"Tie\n";
}else if(a1%2==0&&b1%2==1){
cout<<"Mai\n";
}else{
cout<<"Ajisai\n";
}
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
/*
1 3 -1 2 0
*/
C2. Renako Amaori and XOR Game (hard version)
题目链接:Problem - C2 - Codeforces
思路:
依次从最高位开始,比较ai和bi中该位数上为1的数的个数。
其余思路和C1一样。
现在主要就是如何把一个数化成二进制的问题。
(a>>k)&1 //结果为1,a化成二进制从右向左数第k位为1;否则为0;
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+12;
int a[N],b[N];
void solve(){
int n;cin>>n;
int a1=0,b1=0;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
for(int i=30;i>=0;i--){
a1=0,b1=0;
for(int j=1;j<=n;j++){
if((a[j]>>i)&1){
a1++;
}
if((b[j]>>i)&1){
b1++;
}
}
for(int j=1;j<=n;j++){
if(((a[j]>>i)&1) != ((b[j]>>i)&1)){
if(a1%2==0&&j%2==1){
if((a[j]>>i)&1) a1--,b1++;
else a1++,b1--;
}
if(b1%2==0&&j%2==0){
if((b[j]>>i)&1) b1--,a1++;
else b1++,a1--;
}
}
}
if(a1%2!=b1%2) break;
}
if(a1%2==b1%2) cout<<"Tie\n";
else if((a1%2==0)&&(b1%2==1)) cout<<"Mai\n";
else cout<<"Ajisai\n";
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
D. Rae Taylor and Trees (easy version)
题目链接:Problem - D - Codeforces
思路:
翻译一下题意,一个数可以和在他后边比他大的数相连,或者和在他前边的比他小的数相连,问是否所有数之间可以相互联通。
所以从第一个数往后遍历:
用cnt记录中间比最小值小的数,p记录最后一个大于最小值的数的位置;
t记录比目前最小值的
- 如果这个数比当前已加入数中最小的数大
- 这个数及这个数之前所有数一定可以联通,他以及他前面所有比当前最小值小的数正式加入;
- 同时更新最小值,将cnt变成0,p=i;
- 如果这个数比当前已加入数中最小的数大
- 找到还没正式加入的数的最小值;cnt+ +;
最后判断一下:
- 如果p==n,输出Yes;
- 否则输出No;
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+12;
int a[N],minn=N,maxx=-1;
void solve(){
int n,cnt=0;cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
minn=a[1],maxx=a[1];
int t=minn,p=0;
for(int i=2;i<=n;i++){
if(a[i]>minn){
cnt=0;minn=t;p=i;
}
else{
t=min(t,a[i]);cnt++;
}
}
if(p==n){
cout<<"Yes\n";return ;
}
else cout<<"No\n";
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
/*
1
6
4 2 6 5 1 3
1
2
2 1
2
2
1 2
2
2 1
*/
F. Rae Taylor and Trees (hard version)
题目链接:Problem - F - Codeforces
思路:
和D题差不多,把cnt换成数组再开个ans数组存以下就好了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+12;
int a[N],minn=N,maxx=-1;
void solve(){
int n;cin>>n;
vector<int> cnt;
vector<pair<int,int>> ans;
for(int i=1;i<=n;i++){
cin>>a[i];
}
minn=a[1],maxx=a[1];
int t=minn,p=0;
for(int i=2;i<=n;i++){
if(a[i]>minn){
ans.push_back({a[i],minn});
for(int j=0;j<cnt.size();j++){
ans.push_back({a[i],cnt[j]});
}
minn=t;p=i;cnt.clear();
}
else{
t=min(t,a[i]);cnt.push_back(a[i]);
}
}
if(p==n){
cout<<"Yes\n";
for(auto i:ans){
cout<<i.first<<" "<<i.second<<"\n";
}return ;
}
else cout<<"No\n";
return ;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}
/*
1
6
4 2 6 5 1 3
1
2
2 1
2
2
1 2
2
2 1
*/