前言
博主也算是毒奶界的一柄利剑。
博主喜欢RNG,RNG无了;
博主喜欢FPX,FPX寄了;
博主之前爱看我英(**东西),结果作者背刺我。
博主在这里毒奶一下,EDG打DK的时候,EDG全员就跟博主刷混沌传送杖的样子一样:刷了2小时毛都没看到,根本看不到胜利的曙光。
国电要是夺冠,第二天速更最后一篇最小生成树算法讲解,并且之后的Atcoder的每一场ABC必出题解。
不破不立,EDG给我冲!
A - Three Piles of Candies(水题)
比赛链接:https://codeforces.com/contest/1196/problem/A
题目大意
现在这里有三堆糖果,第一堆糖果有
a
a
a个,第二堆有
b
b
b个,第三堆有
c
c
c个。
我们想把这三堆糖果平分给两个人,使得两个人最后得到的糖果数量都是
x
x
x个。
求出 x x x的最大值。
思路
啊?这种题你都要看题解的?
建议原地给自个埋了吧。
AC代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--){
ll a,b,c;
cin>>a>>b>>c;
cout<<(a+b+c)/2<<endl;
}
}
B - Odd Sum Segments (思维+数学)
比赛链接:https://codeforces.com/contest/1196/problem/B
题目大意
给出长度为n的数组a,问是否可以把数组a分割为k个子数组,使得所有子数组的和都是奇数。
如果可以实现,则输出“YES”,并输出一种可行方案;
否则输出“NO”。
例如,样例1中7 18 3 14 1
可以分割为7
、18 3
与14 1
,所以输出的是1 3 5
,分别代表着7、3、1
在数组中的下标,意味着把区间
[
1
,
1
]
,
[
2
,
3
]
,
[
4
,
5
]
[1 , 1],[2 , 3],[4 , 5]
[1,1],[2,3],[4,5]各分一组。
思路
这又涉及到了小学数学的知识,详细请见博主在Codeforces Round #753 (Div. 3)部分题解(A ~ E题)中B题的解释。
我们记录下数组中所有奇数的位置。
-
如果奇数的个数少于k个,那么我们就无法实现题目中的要求(影响每个数组和的奇偶性的因素不在于偶数的个数,而是在于奇数的个数)。
-
如果奇数的个数大于 k k k个,我们可以让前( k − 1 k-1 k−1)个数组每个数组都拿走一个奇数,偶数随便拿,这就能保证前 k − 1 k-1 k−1个数组的和一定是奇数。 然后我们把剩下的奇数都分给最后一个数组,这个时候最后一个数组中奇数的个数就决定了这道题的答案。
AC代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
ll a[maxn];
int main()
{
ios::sync_with_stdio(false);
int t;
cin>>t;
while(t--)
{
int n,k;
vector<int> ans;
cin>>n>>k;
for(int i=1; i<=n; i++){
cin>>a[i];
if(a[i]&1) ans.push_back(i);
}
if(ans.size()<k||(ans.size()-k+1)%2==0) cout<<"NO"<<endl;
else{
cout<<"YES"<<endl;
for(int i=0;i<k-1;i++)
cout<<ans[i]<<" ";
cout<<n<<endl;
}
}
}
C - Robot Breakout(思维)
比赛链接:https://codeforces.com/contest/1196/problem/C
题目大意
从实验室中跑出了一群暴走的机器人,它们还处于试验阶段,十分的危险。
现在你运用自己的智慧暂时性把所有的机器人都控制了起来,但是它们散落在各处,收集起来十分麻烦,于是你想给所有机器人发送一个坐标,使得所有的机器人都能到达那个坐标,以便于实验室的回收。
由于机器人还处于实验阶段,致使有些机器人还没有被完善。
机器人
i
i
i有6个属性:
X
i
X_i
Xi、
Y
i
Y_i
Yi、
f
i
,
1
f_{i,1}
fi,1、
f
i
,
2
f_{i,2}
fi,2、
f
i
,
3
f_{i,3}
fi,3、
f
i
,
4
f_{i,4}
fi,4。
- X i X_i Xi、 Y i Y_i Yi代表着机器人 i i i现在处于( X i X_i Xi, Y i Y_i Yi)的位置;
- 若 f i , 1 = 0 f_{i,1}=0 fi,1=0,则代表机器人 i i i无法进行( X i X_i Xi, Y i Y_i Yi) → ( X i − 1 X_i-1 Xi−1, Y i Y_i Yi)的行动;若 f i , 1 = 1 f_{i,1}=1 fi,1=1,则代表机器人 i i i可以进行( X i X_i Xi, Y i Y_i Yi) → ( X i − 1 X_i-1 Xi−1, Y i Y_i Yi)的行动。
- 若 f i , 2 = 0 f_{i,2}=0 fi,2=0,则代表机器人 i i i无法进行( X i X_i Xi, Y i Y_i Yi) → ( X i X_i Xi, Y i + 1 Y_i+1 Yi+1)的行动;若 f i , 2 = 1 f_{i,2}=1 fi,2=1,则代表机器人 i i i可以进行( X i X_i Xi, Y i Y_i Yi) → ( X i X_i Xi, Y i + 1 Y_i+1 Yi+1)的行动。
- 若 f i , 3 = 0 f_{i,3}=0 fi,3=0,则代表机器人 i i i无法进行( X i X_i Xi, Y i Y_i Yi) → ( X i + 1 X_i+1 Xi+1, Y i Y_i Yi)的行动;若 f i , 3 = 1 f_{i,3}=1 fi,3=1,则代表机器人 i i i可以进行( X i X_i Xi, Y i Y_i Yi) → ( X i + 1 X_i+1 Xi+1, Y i Y_i Yi)的行动。
- 若 f i , 4 = 0 f_{i,4}=0 fi,4=0,则代表机器人 i i i无法进行( X i X_i Xi, Y i Y_i Yi) → ( X i X_i Xi, Y i + 1 Y_i+1 Yi+1)的行动;若 f i , 4 = 1 f_{i,4}=1 fi,4=1,则代表机器人 i i i可以进行( X i X_i Xi, Y i Y_i Yi) → ( X i X_i Xi, Y i + 1 Y_i+1 Yi+1)的行动。
当机器人收到一个坐标时它会自动进行寻路并前往。
现在请找到一个坐标,使得所有的机器人在收到坐标之后都可以到达那个坐标。
如果存在这个坐标则输出"
1
X
Y
1 X Y
1XY",其中
(
X
,
Y
)
(X,Y)
(X,Y)为你所找到的那个坐标。
如果不存在则输出0。
思路
十分简单的思维题。
我们只需要找到所有机器人的活动范围的交集部分,这个部分内的所有点都可以是答案。
这是第二个样例中三个机器人的活动范围,图画的丑了点,就乎着看吧。
处在
(
1
,
5
)
(1,5)
(1,5)处的机器人可以向所有方向行动,所以它的活动范围就是整个二维图;
处在
(
2
,
5
)
(2,5)
(2,5)处的机器人只能上下移动,所以它的活动范围就是
x
=
2
x=2
x=2这条红色直线;
处在
(
3
,
5
)
(3,5)
(3,5)处的机器人只能向左移动,所以它的活动范围就是绿色的直线;
而这三个机器人活动范围的交集就是点
(
2
,
5
)
(2,5)
(2,5)。所以答案是
(
2
,
5
)
(2,5)
(2,5)。
AC代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
int a[maxn][10];
int main()
{
ios::sync_with_stdio(false);
int q;
cin>>q;
while(q--){
int n;
cin>>n;
for(int i=0;i<n;i++)
for(int j=0;j<6;j++)
cin>>a[i][j];
//最后答案的X、Y的上限是100000
int mxx=100000,mix=-100000;
int may=100000,miy=-100000;
for(int i=0;i<n;i++){
if(a[i][2]==0) mix=max(a[i][0],mix);
if(a[i][3]==0) may=min(a[i][1],may);
if(a[i][4]==0) mxx=min(a[i][0],mxx);
if(a[i][5]==0) miy=max(a[i][1],miy);
}
if(mxx>=mix&&may>=miy){
cout<<"1 "<<mxx<<" "<<may<<endl;
}
else cout<<"0"<<endl;
}
}
D1 - RGB Substring (easy version) (暴力)
比赛链接:https://codeforces.com/contest/1196/problem/D1
题目大意
给出一个字符串s。
问你至少需要改变字符串
s
s
s中的几个字符,才能使得字符串
s
s
s的一个长度为
k
k
k的子串
s
′
s'
s′同时也是"
R
G
B
R
G
B
R
G
B
R
G
B
R
G
.
.
.
RGBRGBRGBRGBRG...
RGBRGBRGBRGBRG..."的子串?
本题中字符串 s s s的长度最多为 2000 2000 2000。
思路
2000
2000
2000的长度?
2
2
2秒?
这意味着什么不用我多说了吧,暴力干它就完事了。
不过要注意的是s’的形式有三种:RGBRGBR...
,GBRGBRGBR..
与BRGBRGBR...
,符合任意一种即可。
AC代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+100;
int main()
{
ios::sync_with_stdio(false);
int q;
cin>>q;
while(q--){
int n,k;
int minx=inf;
string ss;
cin>>n>>k;
cin>>ss;
for(int i=0;i<=n-k;i++)
{
string s=ss.substr(i,k);
string words="RGB";
for(int j=0;j<3;j++){
int l=j,cnt=0;
string str="";
while(cnt<k){
str+=words[l];
l++;
if(l==3) l=0;
cnt++;
}
int x=0;
for(int z=0;z<k;z++)
if(s[z]!=str[z])
x++;
minx=min(x,minx);
}
}
cout<<minx<<endl;
}
}
D2 - RGB Substring (hard version)(前缀和)
比赛链接:https://codeforces.com/contest/1196/problem/D2
题目大意
给出一个字符串s。
问你至少需要改变字符串
s
s
s中的几个字符,才能使得字符串
s
s
s的一个长度为
k
k
k的子串
s
′
s'
s′同时也是"
R
G
B
R
G
B
R
G
B
R
G
B
R
G
.
.
.
RGBRGBRGBRGBRG...
RGBRGBRGBRGBRG..."的子串?
本题中字符串 s s s的长度最多为 2 e 5 2e5 2e5。
思路
出题人:“就你搁这暴力是吧?挺猖狂啊?”
数据量加大了而已,有什么好怕的。
既然正着想(还差多少个字符才符合)行不通,那么我反着想(已经有多少个字符是符合的)总没问题吧。
首先我们要知道,如果
a
′
a'
a′是
a
a
a的子串,
a
′
′
a''
a′′是
a
′
a'
a′的子串,那么根据继承关系,
a
′
′
a''
a′′也是
a
a
a的子串。
那我们就创建三个不同的"
R
G
B
R
G
B
R
G
B
R
G
B
R
G
.
.
.
RGBRGBRGBRGBRG...
RGBRGBRGBRGBRG..."的子串:
1.RGBRGBR...
2.GBRGBRG...
3.BRGBRGB...
然后我们再设定一个前缀和数组sum
,sum[i][j]
代表的是字符串s的前j个字符中与上面的第i个字符串前j个字符有多少个字符是同位置并相同的个数
。
字符串s:BGGGG
一号串:RGBRG
sum :01112
这样我们就可以求出字符串s中最多可以匹配上的字符的个数,再用k减去不就是答案吗?
AC代码
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=2e5+100;
string words="RGB";
int sum[5][maxn];
int main()
{
ios::sync_with_stdio(false);
int q;
cin>>q;
while(q--)
{
int n,k;
int maxx=-1;
string ss;
string str[4];
cin>>n>>k;
cin>>ss;
for(int j=0; j<3; j++)
{
int l=j,cnt=0;
str[j]="";
while(cnt<n)
{
str[j]+=words[l];
l++;
if(l==3)
l=0;
cnt++;
}
}
sum[0][0]=sum[1][0]=sum[2][0]=0;
for(int i=0;i<n;i++){
if(ss[i]==str[0][i]) sum[0][i+1]=sum[0][i]+1;
else sum[0][i+1]=sum[0][i];
if(ss[i]==str[1][i]) sum[1][i+1]=sum[1][i]+1;
else sum[1][i+1]=sum[1][i];
if(ss[i]==str[2][i]) sum[2][i+1]=sum[2][i]+1;
else sum[2][i+1]=sum[2][i];
}
for(int i=1;i<=n-k+1;i++){
maxx=max(maxx,sum[0][i+k-1]-sum[0][i-1]);
maxx=max(maxx,sum[1][i+k-1]-sum[1][i-1]);
maxx=max(maxx,sum[2][i+k-1]-sum[2][i-1]);
}
cout<<k-maxx<<endl;
}
}
后话
感谢阅读,希望能对你产生一点用处。
以下台词取自《银魂》第80集:
(银八混打,帅呆了(❤´艸`❤))