Codeforces Round 923 (Div. 3)

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();
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

louisdlee.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值