Codeforces Round #684 (Div. 2)
传送门(点击传送)
A. Buy the String
题意:
有长度为n的二进制串,你可以花费h的价格把任意一位置反( 1 改 0 ,0 改 1 )。然后你要买下这个二进制串,每个 1 你需要花费 c 1 c_1 c1 元,每个 0 你需要花费 c 0 c_0 c0 元。问最少需要多少钱可以买下二进制串。( t 组数据)
思路:
枚举整个串有 0 个 0 到有 n 个 0 ,其中的最小值即为答案。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t,n,c0,c1,h;
string s;
cin>>t;
while(t--){
int ans=0x7fffffff,cont0=0,sum;
cin>>n>>c0>>c1>>h;
cin>>s;
for(int i=0;i<n;i++){
if(s[i]=='0')cont0++;
}
for(int i=0;i<=n;i++){
sum=abs(cont0-i)*h;
sum+=i*c0+(n-i)*c1;
ans=min(ans,sum);
}
cout<<ans<<endl;
}
return 0;
}
B. Sum of Medians
题意:
有一个序列有 n × k n\times k n×k个元素,现在让你把这个序列分成 k 组,每组的中位数为该组从小到大排序后的第 ⌈ n 2 ⌉ \left \lceil \frac{n}{2} \right \rceil ⌈2n⌉个数,现在让求出所有中位数之和的最大值是多少。( t 组数据)
思路:
贪心,先把所有数排序,把前面的 ⌊ n − 1 2 ⌋ × k \left \lfloor \frac{n-1}{2} \right \rfloor \times k ⌊2n−1⌋×k 个数放在每组的中位之前,这样可以保证最小的数都不被用到,之后每放置一个中位数,中位数后都放置比它大的尽量小的数。即可求得最大值。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
int num[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int t,n,k;
cin>>t;
while(t--){
cin>>n>>k;
for(int i=1;i<=n*k;i++){
cin>>num[i];
}
sort(num+1,num+1+n*k);
ll ans=0;
int loc=(n-1)/2*k;
for(int i=loc+1;i<=n*k;i+=n-(n-1)/2){
ans+=1ll*num[i];
}
cout<<ans<<endl;
}
return 0;
}
C1. Binary Table (Easy Version)
题意:
有 n × m n \times m n×m的二进制矩阵,你每次操作可以选一个 2 × 2 2\times2 2×2的矩阵,把其中的三个元素取反( 1 改 0 ,0 改 1 )。最多操作 3 n m 3nm 3nm 次,把所有元素都改为 0 ,请输出操作次数和每次操作选的 3 个位置。( t 组数据)
思路:
对于 2 × 2 2\times2 2×2的格子的所有情况,除了全是 1 的情况外,所有情况皆可以在操作3次及3次以内让所有元素变为 0 ,所以我们对每个 2 × 2 2\times2 2×2的格子进行情况匹配即可完成。我们分为如下4个操作:每个操作都是红色区域取反。
一共16中情况我们可以分别考虑:
- 全为0:不用操作。
- 左上角为1,其余为0:进行操作1,操作2,操作3。
- 右上角为1,其余为0:进行操作2,操作1,操作4。
- 左下角为1,其余为0:进行操作3,操作1,操作4。
- 右下角为1,其余为0:进行操作4,操作2,操作3。
- 左上右上为1:进行操作3,操作4。
- 左上左下为1:进行操作2,操作4。
- 左上右下为1:进行操作1,操作4。
- 右上左下为1:进行操作2,操作3。
- 右上右下为1:进行操作1,操作3。
- 左下右下为1:进行操作1,操作2。
- 左上,右上,左下为1:进行操作1。
- 左上,右上,右下为1:进行操作2。
- 左上,左下,右下为1:进行操作3。
- 右上,左下,右下为1:进行操作4。
- 全为1:进行操作4,操作1,操作2,操作3。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=110;
char c[maxn][maxn];
vector<pair<int,int> >vec;
int t,n,m;
void change1(int x,int y){
vec.push_back({
x,y});vec.push_back({
x,y+1});vec.push_back({
x+1,y});
}
void change2(int x,int y){
vec.push_back({
x,y});vec.push_back({
x,y+1});vec.push_back({
x+1,y+1});
}
void change3(int x,int y){
vec.push_back({
x,y});vec.push_back({
x+1,y});vec.push_back({
x+1,y+1});
}
void change4(int x,int y){
vec.push_back({
x,y+1});vec.push_back({
x+1,y});vec.push_back({
x+1,y+1});
}
void solve(int x,int y){
if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
return;
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change1(x,y);change2(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change2(x,y);change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change3(x,y);change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change4(x,y);change2(x,y);change3(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change3(x,y);change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change2(x,y);change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change2(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change1(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change1(x,y);change2(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change1(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change2(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change4(x,y);change1(x,y);change2(x,y);change3(x,y);
}
c[x][y]='0';c[x+1][y]='0';c[x][y+1]='0';c[x+1][y+1]='0';
}
int main()
{
scanf("%d",&t);
while(t--){
vec.clear();
scanf("%d %d\n",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",c[i]+1);
}
for(int i=1;i<n;i++){
for(int j=1;j<m;j++){
solve(i,j);
}
}
printf("%d\n",vec.size()/3);
for(int i=0;i<vec.size();i+=3){
printf("%d %d %d %d %d %d\n",vec[i].first,vec[i].second,vec[i+1].first,vec[i+1].second,vec[i+2].first,vec[i+2].second);
}
}
return 0;
}
C2. Binary Table (Hard Version)
题意:
上一题的困难版本有 n × m n \times m n×m的二进制矩阵,你每次操作可以选一个 2 × 2 2\times2 2×2的矩阵,把其中的三个元素取反( 1 改 0 ,0 改 1 )。最多操作 n m nm nm 次,把所有元素都改为 0 ,请输出操作次数和每次操作选的 3 个位置。( t 组数据)
思路:
我们还是一行一行改,除最后两行外,我们每一个 2 × 2 2\times2 2×2的矩阵如果矩阵的左上角为1,那么我们都采取如下几种操作:若右上为1,则采用操作1,否则采用操作3。对于最右边的 2 × 2 2\times2 2×2矩阵我们要单独判断,若右上为1则采用操作4。就这样,我们把所有的 1 转移到最后两行。对于最后两行,我们从左往右枚举 2 × 2 2\times2 2×2矩阵,若左上左下都为1,则采用操作1;若左上为1左下为0,则采用操作2;若左上为0,左下为1则采用操作4。如此操作我们将所有的1转移到最右边的矩阵中。最后对最右边的 2 × 2 2\times2 2×2矩阵做处理即可。操作次数最多为 ( ⌊ m 2 ⌋ + 1 ) × ( n − 2 ) + ( m − 2 ) + 4 (\left \lfloor \frac{m}{2} \right \rfloor+1)\times(n-2)+(m-2)+4 (⌊2m⌋+1)×(n−2)+(m−2)+4是小于 n m nm nm的。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=110;
char c[maxn][maxn];
vector<pair<int,int> >vec;
int t,n,m;
void make_solve(int x,int y){
if(c[x][y]=='1') c[x][y]='0';
else c[x][y]='1';
}
void change1(int x,int y){
vec.push_back({
x,y});vec.push_back({
x,y+1});vec.push_back({
x+1,y});
make_solve(x,y);make_solve(x,y+1);make_solve(x+1,y);
}
void change2(int x,int y){
vec.push_back({
x,y});vec.push_back({
x,y+1});vec.push_back({
x+1,y+1});
make_solve(x,y);make_solve(x,y+1);make_solve(x+1,y+1);
}
void change3(int x,int y){
vec.push_back({
x,y});vec.push_back({
x+1,y});vec.push_back({
x+1,y+1});
make_solve(x,y);make_solve(x+1,y);make_solve(x+1,y+1);
}
void change4(int x,int y){
vec.push_back({
x,y+1});vec.push_back({
x+1,y});vec.push_back({
x+1,y+1});
make_solve(x,y+1);make_solve(x+1,y);make_solve(x+1,y+1);
}
void solve(int x,int y){
if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
return;
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change1(x,y);change2(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change2(x,y);change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change3(x,y);change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change4(x,y);change2(x,y);change3(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='0'){
change3(x,y);change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change2(x,y);change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change1(x,y);change4(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change2(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change1(x,y);change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change1(x,y);change2(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='0'){
change1(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='0' && c[x+1][y+1]=='1'){
change2(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='0' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change3(x,y);
}else if(c[x][y]=='0' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change4(x,y);
}else if(c[x][y]=='1' && c[x][y+1]=='1' && c[x+1][y]=='1' && c[x+1][y+1]=='1'){
change4(x,y);change1(x,y);change2(x,y);change3(x,y);
}
}
int main()
{
scanf("%d",&t);
while(t--){
vec.clear();
scanf("%d %d\n",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",c[i]+1);
}
for(int i=1;i<n-1;i++){
for(int j=1;j<m;j++){
if(c[i][j]=='1'){
if(c[i][j+1]=='1'){
change1(i,j);
}else{
change3(i,j);
}
}
}
if(c[i][m]=='1'){
change4(i,m-1);
}
}
for(int i=1;i<m-1;i++){
if(c[n-1][i]=='1'){
if(c[n][i]=='1'){
change1(n-1,i);
}else{
change2(n-1,i);
}
}else{
if(c[n][i]=='1'){
change4(n-1,i);
}
}
}
solve(n-1,m-1);
printf("%d\n",vec.size()/3);
for(int i=0;i<vec.size();i+=3){
printf("%d %d %d %d %d %d\n",vec[i].first,vec[i].second,vec[i+1].first,vec[i+1].second,vec[i+2].first,vec[i+2].second);
}
}
return 0;
}