A - Three Piles of Candies
题意:
A和B分糖果,一共有三堆糖果,A可以先挑一堆糖果,B在挑一堆糖果,之后有平分操作,A和B希望糖果数相等,所以多的人会丢糖果,最后一堆糖果由A和B分,最后在执行平分操作,求A能得到的最大糖果数
思路:
先拿两堆后平分,第三堆糖果在分配后平分,因为糖果多的人会丢掉,所以求和除以2即可(记得关输入输出流或使用scanf)
代码:
#include<iostream>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int t;;
cin>>t;
while(t--)
{
long long a,b,c,sum=0;
cin>>a>>b>>c;
sum=(a+b+c)/2;
cout<<sum<<endl;
}
}
B - Odd Sum Segments
题意:
q次查询,每次查询输入一个n和k,你有一个n个元素的数组,你需要把这个数组分成k段,如果每能分成k段的后每个段元素和为奇数,输出YES,并输出k个元素段的元素右侧端点位置,若分成k段的后每段元素和不为奇数输出NO
思路:
奇数+奇数=偶数,奇数+偶数=偶数,偶数+偶数=偶数
所以我们要找奇数的个数和位置,而当奇数的个数的奇偶性和k的奇偶性相同时才有可能使每个段元素和为奇数(你可以试试一些数5,6 | 7,9)当然奇数个数一定要大于等于k才可以。
代码:
#include<iostream>
using namespace std;
int a[210000];
int main()
{
ios::sync_with_stdio(false);
int t;;
cin>>t;
while(t--)
{
int n,k,sum=0;
cin>>n>>k;
for(int i=1; i<=n; i++)
{
cin>>a[i];
if(a[i]%2==1)
sum+=1; //奇数
}
if(sum%2==k%2&&sum>=k)
{
cout<<"YES"<<endl;
for(int i=1,cnt=1; i<=n&&cnt<=k-1; i++)
{
if(a[i]%2==1)
{
cout<<i<<" ";
cnt+=1;
}
}
cout<<n<<endl;
}
else
cout<<"NO"<<endl;
}
}
C - Robot Breakout
题意:
q个查询,每个查询下输入一个n表示机器人的个数,之后n行x,y表示机器人的位置f1,f2,f3,f4为其左上右下四个方向是否可以移动,而每个方向都有对应的 f j = 1 或0 ,等于1代表可以移动,0则不能移动,求一个坐标(X,Y) 使得所有机器人都能够到达。而机器人停止移动当且仅当机器人到达了x,y或无法到达x,y。
思路:
我们根据输入的机器人位置可以确定界限,而根据每个机器人能走的方向可以缩小边界,当确定最小的边界时输出一个边界值即可。
代码:
#include<iostream>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int t;;
cin>>t;
while(t--)
{
int n;
cin>>n;
int left=-1e5,down=-1e5;
int right=1e5,up=1e5;
while(n--)
{
int x,y,f1,f2,f3,f4;
cin>>x>>y>>f1>>f2>>f3>>f4;
if(f1==0)
left=max(left,x);
if(f4==0)
down=max(down,y);
if(f2==0)
up=min(up,y);
if(f3==0)
right=min(right,x);
}
if(left>right||down>up)
cout<<0<<endl;
else
cout<<1<<" "<<left<<" "<<up<<endl;
}
}
D - RGB Substring (easy version)
题意:
q 组询问,每组给出一个长度为 n 的字符串与一个 "RGBRGBRGB..." 循环子串的长度 k,
现在要所给的长度为 n 的子串中选择一个长度为 k 的子串,对其进行任意次代价为 1 的更改,
即可将任意一个字符改为其他字符,使得这个子串与 "RGBRGBRGB..." 循环子串所匹配,求最小代价。
思路:
枚举把每个字符都修改为‘R‘ ’G‘ ’B’ ,开一个二维数组,记录更改的开销,
如果是他本身那么开销为0,其余两个都为1。初始化完了之后,用一个长度为k的滑动窗口,
右边收录一个字符,加上对应的开销,而左边删去一个字符,减去对应的开销。
同样是要枚举三种情况,每一次移动都结算一次最小值,最后得到的就是全局最优解。
那么这个窗口在初始化的时候,首先需要收录k个字符,先记录下他们的开销,以及开始和结束位置,接下来遍历整个串就行了,复杂度O(3*n)。
代码:
#include <bits/stdc++.h>
const int N = 1e6+10;
using namespace std;
int a[N][3]; // 记录每个字符的开销
map<char,int> mp; // 把字符映射成数字,便于处理
int main()
{
int n,m;
mp['R'] = 0;
mp['G'] = 1;
mp['B'] = 2;
string s;
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>s;
for(int i = 0 ; i < n ; i ++ ) // 初始化开销数组
{
a[i][mp[s[i]]] = 0;
a[i][(mp[s[i]]+1)%3] = 1;
a[i][(mp[s[i]]+2)%3] = 1;
}
int head1,head2,head3;
int tail1,tail2,tail3;
int sum1,sum2,sum3;
head1 = 0 ;
head2 = 1 ;
head3 = 2 ;
tail1 = 0 ;
tail2 = 1 ;
tail3 = 2 ;
sum1 = sum2 = sum3 = 0;
for(int i = 0 ; i < m ; i ++) // 初始化长度为K的窗口
{
sum1 += a[i][head1];
sum2 += a[i][head2];
sum3 += a[i][head3];
head1 = (head1+1)%3;
head2 = (head2+1)%3;
head3 = (head3+1)%3;
}
int ans = min(sum1,min(sum2,sum3));
for(int i = m ; i < n ; i ++) // 遍历数组,更新最小值
{
sum1 += a[i][head1];
sum2 += a[i][head2];
sum3 += a[i][head3];
sum1 -= a[i-m][tail1];
sum2 -= a[i-m][tail2];
sum3 -= a[i-m][tail3];
head1 = (head1+1)%3;
head2 = (head2+1)%3;
head3 = (head3+1)%3;
tail1 = (tail1+1)%3;
tail2 = (tail2+1)%3;
tail3 = (tail3+1)%3;
ans = min(min(ans,sum1),min(sum2,sum3));
}
cout << ans << endl;
}
return 0;
}
待更~~~