Codeforces Round #821 (Div. 2) ABCD1
A.Consecutive Sum
https://codeforces.com/contest/1733/problem/A
题目大意:
给定一个长度为n的数组a。最多可以执行k次以下操作:
选择两个指数i和j,其中i mod k=j mod k (1≤i<j≤n)。
互换ai和aj。
完成所有操作后,你必须选择k个连续的元素,这k个元素的总和就是你的分数。找到你能得到的最高分。
input
5
3 2
5 6 0
1 1
7
5 3
7 0 4 0 4
4 2
2 7 3 4
3 3
1000000000 1000000000 999999997
output
11
7
15
10
2999999997
数据范围小,直接双重循环暴力跑即可
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int N=2002000,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n,k;
cin>>n>>k;
for(LL i=1;i<=n;i++)
{
cin>>a[i];
}
LL sum=0;
for(LL i=1;i<=k;i++)
{
LL maxn=a[i];
for(LL j=i;j<=n;j+=k)
{
maxn=max(maxn,a[j]);
}
sum+=maxn;
}
cout<<sum<<endl;
}
return 0;
}
B. Rule of League
https://codeforces.com/contest/1733/problem/B
题目大意:
n个人编号1-n在一起打羽毛球,从1和2开始两两打(1和2打一局,赢了的和3打,赢了的和4打...)
总共会打n-1局,给定一个x,y,分别表示每个人可能赢的次数和输的次数
问合理嘛?合理给出每一局可能赢的人数,不合理输出-1。
input
5
5 2 0
8 1 2
3 0 0
2 0 1
6 3 0
output
1 1 4 4
-1
-1
2
-1
根据题目意思,每x或者y盘安排一个人赢即可
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int N=2002000,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n,x,y;
cin>>n>>x>>y;
if(x!=0&&y!=0) cout<<"-1"<<endl;
else if(x==0&&y==0) cout<<"-1"<<endl;
else
{
if(x!=0)
{
if((n-1)%x!=0) cout<<"-1"<<endl;
else
{
for(LL i=2;i<=n;i+=x)
for(LL j=1;j<=x;j++)
cout<<i<<" ";
cout<<endl;
}
}
else if(y!=0)
{
if((n-1)%y!=0) cout<<"-1"<<endl;
else
{
for(LL i=2;i<=n;i+=y)
for(LL j=1;j<=y;j++)
cout<<i<<" ";
cout<<endl;
}
}
}
}
return 0;
}
C. Parity Shuffle Sorting
https://codeforces.com/contest/1733/problem/C
题目大意:
给定一个长度为n的非负整数的数组a。
可以对其应用以下操作(至多n次):
选择两个指数l和r (1≤l<r≤n),如果al+ar是奇数,则做ar:=al。如果al+ar是偶数,则做al:=ar。
(如果ai+aj是奇数,那么右边的数字变成和左边的一样;如果ai+aj是偶数,那么左边的数字变成和右边的一样)。
找出最多n个运算的任意序列,使数组a变成非递减的顺序。可以证明,总是有可能的。请注意,您不必最小化操作的数量。
输出任意一种操作方案。
input
3
2
7 8
5
1 1000000000 3 0 5
1
0
output
0
2
3 4
1 2
0
年度最离谱,写了个假的智慧数据hack了自己的想法,本来半个小时就可以写完的,直接花了一个小时哈哈哈(还是之前的思路),我真是傻了
- 分奇偶,偶奇,偶偶,奇奇四种即可
- 其实合并起来也行,我写的繁琐了些
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int N=2002000,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n;
cin>>n;
for(LL i=1;i<=n;i++)
cin>>a[i];
if(n==1) cout<<"0"<<endl;
else{
if(a[1]%2==1&&a[n]%2==0)//ji ou
{
cout<<n-1<<endl;
cout<<"1 "<<n<<endl;
for(LL i=2;i<=n-1;i++)
{
if(a[i]%2==0) cout<<"1 "<<i<<endl;
else cout<<i<<" "<<n<<endl;
}
}
else if(a[1]%2==0&&a[n]%2==0)//ou ou
{
cout<<n-1<<endl;
cout<<"1 "<<n<<endl;
for(LL i=2;i<=n-1;i++)
{
if(a[i]%2==1) cout<<"1 "<<i<<endl;
else cout<<i<<" "<<n<<endl;
}
}
else if(a[1]%2==0&&a[n]%2==1)//ou ji
{
cout<<n-1<<endl;
cout<<"1 "<<n<<endl;
for(LL i=2;i<=n-1;i++)
{
if(a[i]%2==1) cout<<"1 "<<i<<endl;
else cout<<i<<" "<<n<<endl;
}
}
else if(a[1]%2==1&&a[n]%2==1)//ji ji
{
cout<<n-1<<endl;
cout<<"1 "<<n<<endl;
for(LL i=2;i<=n-1;i++)
{
if(a[i]%2==1) cout<<i<<" "<<n<<endl;
else cout<<"1 "<<i<<endl;
}
}
}
}
return 0;
}
D1. Zero-One (Easy Version)
https://codeforces.com/contest/1733/problem/D1
题目大意:
给你两个二进制字符串a和b,长度都是n。
选择两个索引l和r(l<r):0 变 1,1 变 0。可以操作任意次。
如果l+1=r,则操作的成本为x,否则,成本为y。
你必须找到使a等于b所需的最小成本,或者说没有办法这样做(则输出-1)。
input
4
5 8 7
01001
00101
5 7 2
01000
11011
7 8 3
0111001
0100001
5 10 1
01100
01100
output
8
-1
6
0
贪心:
分三种情况讨论
-
首先是考虑一下什么时候为-1呢?两个两个一组进行交换,那必然是落单了的时候,即为-1;
-
那么如果不存在连续的情况的时候,那我们就只能老老实实的用y来进行计算,可以知道的是我们让其中的两两一组,就可以简化为sum/2*y的总数了
-
那么如果存在连续的情况下呢?
第一种就是有连续的,但是也有非连续的,也有好多对连续的,这种我们可以把它归为一类,因为只要交错进行计算,就可以回到上面那种不连续的情况下
所以比较的种类就可以有这两种:min(sum/2y,ansx+(sum-ans2)/2y)
第二种是的确有连续的,但是没有别的数据作为交叉环节,所以就是只有唯一的这一对相邻的数据,总数也就是只有两个,那这个就必须用相邻的来跟拆分的对比了
也就是min(ansx,ans2*y)
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
typedef long long LL;
const int N=2002000,M=2002;
LL a[N];
int main()
{
cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
LL T=1;
cin>>T;
while(T--)
{
LL n,x,y;
cin>>n>>x>>y;
string s;
cin>>s;
string c;
cin>>c;
LL sum=0;
for(LL i=0;i<s.size();i++)
if(s[i]!=c[i]) sum++;
//cout<<sum<<endl;
LL ans=0;
for(LL i=0;i<s.size();i++)
{
if(i-1>=0&&s[i]!=c[i]&&s[i-1]!=c[i-1])
{
ans++;
i++;
}
}
//cout<<ans<<endl;
if(sum%2==1) cout<<"-1"<<endl;
else
{
//不存在相邻的,直接抵消
if(ans==0) cout<<sum/2*y<<endl;
else
{
//存在相邻的,要么两两互消,要么再拉一个数据
if(sum==2&&ans==1) cout<<min(ans*x,ans*2*y)<<endl;
else cout<<min(sum/2*y,ans*x+(sum-ans*2)/2*y)<<endl;
}
}
s.clear();
c.clear();
}
return 0;
}