Codeforces Round #661 (Div. 3)
A. Remove Smallest
题意:您可以选择两个索引i和j(i≠j),以使ai和aj之间的绝对差不超过一个(| ai-aj |≤1),并删除这两个元素中的最小值。如果两个元素相等,则可以删除其中任何一个(但只能删除一个)。
您的任务是查找是否可以使用多次(可能为零)此类移动来获取仅包含一个元素的数组。
思路:排序后的相邻两个如果差值大于1就不行。
代码
#include <iostream>
#include <math.h>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include<queue>
using namespace std;
#define INF 1000000
typedef pair<int,int>P;
int n,a[100];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
int flag=0;
for(int i=1; i<n; i++)
{
if(a[i]-a[i-1]>1)
{
flag=1;
break;
}
}
if(flag==1)
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
B. Gifts Fixing
题意:在移动过程中,您可以选择1≤i≤n的礼物并执行以下操作之一:
从此礼物中只吃一个糖果(将AI减一);
从此礼物中只吃一个橙子(将bi减一);
从此礼物中只吃一个糖果和一个橙子(将ai和bi都减一)。
当然,如果礼物中没有糖果或橙子,就不能吃(所以ai和bi都不能小于零)。
如上所述,所有礼物应相等。这意味着在经过一系列移动之后,应满足以下两个条件:a1 = a2 =⋯= an和b1 = b2 =⋯= bn(并且ai等于bi并不是必需的)。
您的任务是找到均衡所有给定礼物所需的最小移动次数。
思路:找到最小的a数组里的,找到最小的b数组里的,再一遍for循环,找出a数组与mina差值,b数组与minb的差值,加上大的那个差值,因为可以(将ai和bi都减一)。最后的和就是答案。
代码
#include <iostream>
#include <math.h>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include<queue>
using namespace std;
#define INF 1000000
typedef pair<int,int>P;
int n;
long long a[100],b[100];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
long long mina=1000000000,minb=1000000000;
for(int i=0; i<n; i++)
{
scanf("%lld",&a[i]);
mina=min(a[i],mina);
}
for(int i=0; i<n; i++)
{
scanf("%lld",&b[i]);
minb=min(minb,b[i]);
}
long long ans=0;
//printf("%lld %lld\n",mina,minb);
for(int i=0; i<n; i++)
{
long long ta=a[i]-mina;
long long tb=b[i]-minb;
long long tmp=max(ta,tb);
ans+=tmp;
}
printf("%lld\n",ans);
}
return 0;
}
C. Boats Competition
题意:有n个人想参加划船比赛。第i个参与者的权重是wi。只有两人组成的团队可以参加比赛。如果有k个团队(a1,b1),(a2,b2),…,(ak,bk),其中ai是第i个团队的第一个参与者的权重,bi是第二个团队的权重第i个团队的参与者,则必须满足条件a1 + b1 = a2 + b2 =⋯= ak + bk = s,其中s是每个团队的总权重。问有多少个团队可以参赛。
思路:就是范围都是50,任意两个人的加和最大也就是100,所以用2到100(最小值是1),遍历s,然后再用尺取法,找到有多少对是==i的。最后99遍扫完之后输出最大值。(做题的时候忘记先给数组排序再进行尺取法)。
代码
#include <iostream>
#include <math.h>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <stdio.h>
#include<queue>
using namespace std;
#define INF 1000000
typedef pair<int,int>P;
int n;
int a[100],b[100];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
sort(a,a+n);
int ans=0;
for(int i=2; i<=100; i++)
{
int l=0;
int r=n-1;
int num=0;
while(l<r)
{
if((a[l]+a[r])==i)
{
num++;
l++,r--;
}
else if(a[l]+a[r]>i)
r--;
else if(a[l]+a[r]<i)
l++;
}
ans=max(ans,num);
}
printf("%d\n",ans);
}
return 0;
}
D. Binary String To Subsequences(补)
题意:给定一个字符串由0、1组成,问最少有几个字符串是01间隔的(010101……或者101010……)。输出最少的个数和每个字符在第几个子字符串。
思路:我研究的代码是用两个栈来存,第一个分两个部分,分别存0字符的位置信息,1字符位置信息,另外一个栈存字符串每个位置的位置信息。
举例说明:100011
-
首先第一个字符是1 之前未出现过子字符串,这是第一个,cnt++ (1)1字符栈内先存入cnt,表示这个1字符的位置1号字符串
存入改位置的位置信息。 -
然后是进来0,先看看1号字符串内是否有值,发现有,那这个0的位置信息与1字符串的最前面的相同(先进去的),
0字符栈存入找到的1字符栈的数值(第几个子字符串) 存入改位置的位置信息。
此时要把1字符栈的这个1的位置信息删去,因为已经有出现下一个0,他不可能再接别的0 -
然后还是0,看看1字符栈内没有1了,所以此时的0就要新开一个子字符串,cnt++;(2)
0字符栈内先存入cnt,表示这个0字符的位置2号字符串
存入改位置的位置信息。 -
在之后是0,同上一步操作一样。
-
是1,先判断0字符栈内是否有值,发现有,则存入0字符栈内最前面的子字符串号,再记录再大的位置信息栈中,然后将改信息从0字符站内删除。
-
再来还是1,先判断0字符栈内是否有值,发现有,则存入0字符栈内最前面的子字符串号,再记录再大的位置信息栈中,然后将改信息从0字符站内删除。
就好像是子字符串的号数在0和1的字符栈内只能存在一个
100011
1
‘1’ ①
0
‘1’ ①
‘0’ ①
0
‘0’ ①
‘0’ ②
0
‘0’ ①
‘0’ ②
‘0’ ③
1
‘0’ ①
‘0’ ②
‘0’ ③
‘1’ ①
1
‘0’ ②
‘0’ ③
‘1’ ①
’1‘ ②
代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cin >> t;
while (t--)
{
int n;
cin >> n;
string s;
cin >> s;
int cnt = 0;
vector<int> seq[2];
vector<int> ans;
ans.reserve(n);
for(int i=0; i<n; i++)
{
int x=s[i]-'0';
if(seq[!x].empty())
{
seq[x].push_back(++cnt);
ans.push_back(cnt);
}
else
{
seq[x].push_back(seq[!x].back());
ans.push_back(seq[!x].back());
seq[!x].pop_back();
}
}
cout << cnt << "\n";
for (int i = 0; i < n; ++i)
cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}