Codeforces Round 923 (Div. 3) A~D
文章目录
A. Make it White
模拟
找第一个B和最后一个B 的位置
算出间距即可。
正着找和倒着找。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void slove() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
string s;
cin >> s;
int first;
int last;
for (int i = 0; i < n; i++) {
if (s[i] == 'B') {
first = i;
break;
}
}
//reverse(s.begin(), s.end());
for (int i = n-1; i >=0; i--) {
if (s[i] == 'B') {
last = i;
break;
}
}
cout << last - first + 1 << endl;
}
}
int main() {
slove();
}
B.Following the String
模拟,stl
因为细节,卡了近一小时。
对于字符串 s,和一个字符c
s+=c 和 s=s+c 的时间复杂度是不同的。
前者是O(1),后者是O(n)
嗯。。。。下次注意
正常做法是 O(26n)
但人逼急了什么都做得出来,于是我想到了一个O(n)的做法。
开一个map,出现次数为键,字符为值。
相当于链表吧。
正常做法是 以字符为键,然后循环26次查找出现次数。
O(n)做法
#include<iostream>
#include<string>
#include<vector>
#include<map>
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
typedef long long ll;
const int N=2e5+7;
ll a[N];
void slove() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for(int i=0;i<n;i++)cin>>a[i];
map<int, vector<char> > m;
int cnt = 0;//字母池
string s;
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
char c=cnt+'a';
m[1].push_back(c);
s =s+c;
cnt++;
}
else {
char c=m[a[i]][0];
s+=c;
m[a[i]].erase(m[a[i]].begin());
m[a[i]+1].push_back(c);
}
}
cout << s << '\n';
}
}
int main() {
ios;
slove();
}
O(26n)做法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
void slove() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (auto& i : a)cin >> i;
// for(auto i:a)cout<<i<<' ';
// cout<<endl;
map<char, int> m;
for (int i = 0; i < 26; i++) {
char c=i+'a';
m[c]=0;
}
int cnt = 0;//字母池
string s;
for (int i = 0; i < n; i++) {
if (a[i] == 0) {
char c=cnt+'a';
// cout<<c<<endl;
m[c]++;
s +=c;
cnt++;
}
else {
for (auto it=m.begin();it!=m.end();it++) {
if (it->second == a[i]) {
s += it->first;
// cout<<it->first<<endl;
it->second++;
break;
}
}
}
}
cout << s << endl;
}
}
int main() {
slove();
}
C.Choose the Different Ones!
stl,模拟,思维
将a,b数组内所有的小于等于k的数字都插入到集合a1、b1、 t中。(t是插入a,b元素的总和)
如果t元素个数为k个,那么这是满足的条件之一。
二:计算集合a,b之间重复元素个数,记为chong
三:计算集合a,b之间不重复元素的个数,记为cha
只要chong+cha >= k/2就行。
这是我最后十分钟突然想到的,一发入魂。
有待证明。
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
typedef long long ll;
const int N=1e6+7;
int a[N];
int b[N];
void slove() {
int t;
cin >> t;
while (t--) {
int n,m,k;
cin>>n>>m>>k;
set<int> a1,b1,t1;
for(int i=0;i<n;i++){
cin>>a[i];
if(a[i]<=k){
a1.insert(a[i]);
t1.insert(a[i]);
}
}
for(int i=0;i<m;i++){
cin>>b[i];
if(b[i]<=k){
b1.insert(b[i]);
t1.insert(b[i]);
}
}
if(a1.size()<k/2 or b1.size()<k/2){
cout<<"NO"<<'\n';
continue;
}
int cha=0;
int chong=0;
for(auto it=a1.begin();it!=a1.end();it++){
if(b1.count(*it)){
chong ++;
}
else cha++;
}
if(t1.size()==k and (chong+cha>=k/2)){
cout<<"YES"<<endl;
continue;
}
cout<<"NO"<<'\n';
}
}
int main() {
ios;
slove();
}
D.Find the Different Ones!
思维,模拟
s[i] 等于 i的左边第一个与a[i]不一样的点的下标
如果 a[i]!=a[i-1] , s[i]=i-1; 否则 s[i]=s[i-1];
如果,第i个数与第i-1个数不一样,记录这个不一样的地方的开端:i-1
如果i+1还是不一样的话,那么记录不一样的开端:i
如果后面都一样,那么后面都等于 i
如果区间[l,r] 之间所有数都一样,那么 s[l]=s[r]
否则,我们只要输出 r 和s[r]即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
ll a[N];
void slove() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
for (int i = 1; i <= n; i++)cin >> a[i];
vector<int> cf(n + 2);
cf[1]=0;
for (int i = 2; i <= n; i++) {
if (a[i] != a[i - 1])cf[i] = i-1;
else cf[i] = cf[i - 1];
}
// for(int i=1;i<=n;i++)cout<<cf[i]<<' ';
// cout<<endl;
int q;
cin >> q;
while (q--) {
int l, r;
cin >> l >> r;
if (cf[r] == cf[l]) {
cout << -1 << ' ' << -1 << endl;
}
else {
cout << cf[r] <<' '<< r << endl;
}
}
cout<<endl;
}
}
int main() {
slove();
}
i - 1];
}
// for(int i=1;i<=n;i++)cout<<cf[i]<<' ';
// cout<<endl;
int q;
cin >> q;
while (q--) {
int l, r;
cin >> l >> r;
if (cf[r] == cf[l]) {
cout << -1 << ' ' << -1 << endl;
}
else {
cout << cf[r] <<' '<< r << endl;
}
}
cout<<endl;
}
}
int main() {
slove();
}