Codeforces Round #843 (Div. 2)
本次脑袋不大灵光,一方面可能是怕掉分。另一方面就是交的人实在是太少了,导致我一直不敢交,其实这场cf没有我想象中那么难,甚至来说我一直是有思路的,只不过我思考的不全面而已,之后就因为提交的人数过少而一直不敢交。只能说是太垃圾了!
那就稍微写一些题解来看看自己的一些误区吧
1.
A1. Gardener and the Capybaras (easy version)
A2. Gardener and the Capybaras (hard version) time limit per test1 second
本次cfA有两道,每道题是500分,其实不难的
A1和A2的唯一区别是
The only line of a test case contains the string s (3≤|s|≤100) — the names of the capybaras, written together. The string consists of English letters 'a' and 'b' only.
The only line of a test case contains the string s (3≤|s|≤2e5) — the names of the capybaras, written together. The string consists of English letters 'a' and 'b' only.
唯一的区别是两个字符串的大小有区别,这也就导致了如果第一题实在不会写可以暴力,但是第二题不行
首先来看看暴力的解法
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&-(x))
#define endl '\n'
#define int long long
const int INF = 0x3f3f3f3f;
//using ll=long long;
//using ld=long double;
#define PB push_back
#define MK make_paikk
#define EB emplace_back
#define spa " "
#define kkep(i,n,m) fokk(int i=n;i<=m;i++)
#define kkkkep(i,n,m) fokk(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
//using ll = long long;
typedef long long ll;
const int N = 1010;
int a[N][N];
const int M=10000010;
int b[M];
int n;
void solve() {
int n,m;
string s;
cin>>s;
string a, b, c;
for (int i = 0; i < s.size(); i++) {
for (int j = i+1; j < s.size(); j++) {
a = s.substr(0, i);
b = s.substr(i, j-i);
c = s.substr(j);
if (!a.empty() && !b.empty() && !c.empty()) {
if (b <= a && b <= c) {
cout << a << " " << b << ' ' << c;
return;
}
else if (a <= b && c <= b) {
cout << a << ' ' << b << ' ' << c;
return;
}
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
cout<<endl;
}
}
对于暴力解法,直接截取片段进行比较即可
由于s最大是100,双重循环并不会TLE,但是对于第二题的大小有2e5,经过双重循环的$O(n^2)$,超出了时间限制
那么怎么解决这个问题呢,一开始其实我的思路是对的,我一开始两种思路,第一个是a是第一个,c是最后一个,b是中间一大串,之后发现这种思路不大对,转而开始第二个思路,a是前面到倒数第二个,b是倒数第二个,c是最后一个。
其实这个思路是对的,但是没有具体分析!!!(我当时但凡脑子仔细想想一些都不至于,那么应该咋写呢?)
分情况讨论一下即可:
来代码:
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&-(x))
#define endl '\n'
#define int long long
const int INF = 0x3f3f3f3f;
//using ll=long long;
//using ld=long double;
#define PB push_back
#define MK make_paikk
#define EB emplace_back
#define spa " "
#define kkep(i,n,m) fokk(int i=n;i<=m;i++)
#define kkkkep(i,n,m) fokk(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
//using ll = long long;
typedef long long ll;
const int N = 1010;
int a[N][N];
const int M=10000010;
int b[M];
int n;
void solve(){
string s;
cin>>s;
int n=s.length();
if(s[0]=='a' && s[n-1]=='a'){
cout<<s[0]<<" "<<s.substr(1,n-2)<<" "<<s[n-1]<<'\n';
}
else if(s[0]==s[n-1]){
cout<<s.substr(0,n-2)<<" "<<s[n-2]<<" "<<s[n-1]<<'\n';
}
else{
if(s[1]=='a'){
cout<<s[0]<<" "<<s[1]<<" "<<s.substr(2,n-2)<<'\n';
}
else{
cout<<s[0]<<" "<<s.substr(1,n-2)<<" "<<s[n-1]<<'\n';
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
}
}
很容易,我们发现————
- 如果第一个是a,最后一个也是a,那么b的话我直接输出中间一大串即可,如果中间的是a,三个相等,如果中间的是b,中间的最大,均能满足题目要求
- 同理,如果第一个是b最后一个也是b的话,a我输出从第一个到倒数第二个数,b是倒数第二个数,c是最后一个数,也就是说当我第一个数是b和最后一个数是b的时候,已经注定了中间的是最小的,那么只要我中间的只输出一个数,无论这个数是a还是b,如果这个数是a那么中间的数最小,如果是b,要么相等要么最小,也都满足题目要求
- 好了,以上两点其实我都想到了,但是我没有仔细考虑,所以导致我的思路一直不大对
- 那么之后呢,如果第二个是a的话,那么b就是a,此时b最小,让a是第一个,c是后面一大串就行
- 如果第二个不是a的话,那么此时不用顾虑第一个和最后一个数是什么了,a是第一个,b 是中间一大串,c是最后一个就行,因为如果第一个数是a,最后一个数是b,那么b就是最大的,如果第一个数是b,最后一个数是a的话,那么中间的数就是也是最大的,因为中间的数是b开头,但是a和c最多一个数还不可能都是b
至此,所有情况都讨论完毕,结束!
所以啊,这道题其实不难的,就是一个思维的问题,尤其是只要想到这个思维,根本不会去想暴力。直接白捡1000分数(bushi)(分数是会慢慢减少的)
总体而言,这次的A出的挺有水平的,但是我脑子瓦特了╮(╯_╰)╭
当然除此之外,我当时对于字典序也没有理解对,下面解释一些字典序
我一开始以为是ASKII码,所以导致一开始我对于题目理解也发生了问题,一开始的思路不对,虽然有点丢脸字典序都不会
2.B. Gardener and the Array
第二题比赛的时候完全没有看,其实第二题也不难的
首先来看看案例
- input
5
3
2 1 5
2 2 4
2 2 3
2
2 1 2
1 2
4
3 1 2 4
2 2 4
4 1 2 5 6
2 2 5
5
3 3 1 2
3 2 5 3
5 7 2 3 1 4
5 1 2 6 3 5
3 2 6 3
2
1 1
1 2
- output
No
Yes
Yes
Yes
No
- 题意
给定$n$ 个整数,每个整数给定的形式是某些位上的数是$1$ ,求能不能从$c$ 中获取 $2 $个子序列,使得两个序列内所有数的$or$ 值相同。
这道题主要是题目一直没有看懂,题目看懂了这道题其实很好理解的,尤其是再配合一下案例
这道题的思路就是找是否有某个串是另外一个数的字串,只要是子串那么当异或之后一定是相同的
- 分析
将两个子序列看作两个集合 $a,b$。
尽可能的让其中一个子序列包含尽量多的数,令 $a$集合为 $c$ 内的所有数。接下来我们只需要找到一个没有用的数并把它踢出去就可以,这样的贪心构造是最优秀的,因为一个数对集合的影响是全局的。
如果对于一个数 $c_i$ 的所有位,出现的次数都大于 $1$,那么这个数就是可有可无的,因为一定被 $a$ 这个集合包含,那么 $b$ 集合就是除了$c_i $这个数以外的所有数的集合。构造完毕。
下面给出代码
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&-(x))
#define endl '\n'
#define int long long
const int INF = 0x3f3f3f3f;
//using ll=long long;
//using ld=long double;
#define PB push_back
#define MK make_paikk
#define EB emplace_back
#define spa " "
#define kkep(i,n,m) fokk(int i=n;i<=m;i++)
#define kkkkep(i,n,m) fokk(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
//using ll = long long;
typedef long long ll;
const int N = 1010;
int a[N][N];
const int M=10000010;
int b[M];
int n;
void solve()
{
int n;
cin>>n;
map<int,int> mp;
vector<vector<int>> a(n);
for(int i=0;i<n;i++)
{
int k;
cin>>k;
for(int j=0;j<k;j++)
{
int x;
cin>>x;
a[i].push_back(x);
mp[x]++;
}
}
for(int i=0;i<n;i++)
{
bool flag=true;
for(auto x:a[i])
{
if(mp[x]==1)
flag=false;
// cout<<x<<" ";
// cout<<mp[x]<<" ";
}
if(flag==true)
{
cout<<"YES"<<endl;
return ;
}
}
cout<<"NO"<<endl;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--)
{
solve();
cout<<endl;
}
}
题目理解了其实很好写,直接cheak一下就ok了
标签:843,int,ll,CF,long,using,Div,数是,define From: https://www.cnblogs.com/jiulics/p/17043252.html