codeforces 1251A(簡單簽到) B(思維) C(思維) D(二分+思維)

A. Broken Keyboard(簡單簽到)

題目鏈接:codeforces 1251A

題意:

    鍵盤上有一些鍵壞掉了,壞掉的鍵按一次會出現兩次,給一個按了鍵盤後出現的字符串,現在找出其中其中可能壞掉的鍵

解題思路:

      只要一個字符連續出現的次數爲奇數,那麼這個鍵一定沒壞,比如 aaazz,a鍵一定沒壞,z鍵有可能壞了。

    #include <bits/stdc++.h>
    using namespace std;
    int main(){
    	int t;
    	cin >> t;
    	while(t--){
    		int a[30];
    		memset(a, 0, sizeof(a));
    		string s;
    		cin >> s;
    		int len = s.size();
    		if(len == 1){
    			cout << s << endl;
    			continue;
    		}
    		for(int i = 0; i < len; i++){
    			if(s[i] != s[i+1]){
    				a[s[i]-'a'] = 1;
    			}
    			else{
    				i++;
    			}
     
    		}
    		for(int i = 0; i < 26; i++){
    			if(a[i] == 1){
    				printf("%c", i+'a');
    			}
    		}
    		cout << endl;
    	}
    	return 0;
    }

B. Binary Palindromes(思維)

題目鏈接:codeforces 1251B

題意:

       給出n個字符串(字符串只包含0和1),字符串之間相互交換字符,字符串自身的字符也能相互交換位置(也就是每個字符可以出現在這n個字符串的任何位置),問最多能獲得多少個 迴文串?

解題思路:

    很明顯,只有n和n-1這兩個答案。

   而n-1的情況只有一種情況,就是所有串的長度都爲偶數並且 字符0或1的個數爲奇數的情況

 比如 0111             1100      就只能構成1個迴文串

#include <bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin >> t;
	while(t--){
		string s;
		int n, num0 = 0, k = 0;
		cin >> n;
		for(int i = 1; i <= n; i++){
			cin >> s;
			int len = s.size();
			for(int j = 0; j < len; j++){
				if(s[j] == '0'){
					num0++;
				}
			}
			if(len % 2 == 1){
				k++;
			}
		}
		if(k == 0 && num0 % 2 ==  1){
			cout << n - 1 <<endl;
		}
		else{
			cout << n << endl;
		}
	}
	return 0;
}

C. Minimize The Integer(思維)

題目鏈接:codeforces 1251C

題意:

   給一個數,如果兩個數字相鄰並且奇偶性不同,那麼這兩個數字可以交換位置,問交換後最小的數是多少。

解題思路:

    因爲偶數不能和偶數交換,那麼後一個偶數必定不會交換到前一個偶數之前(無論大小),奇數同理,將奇數和偶數按順序存起來,如果第一奇數比第一個偶數小,那麼先輸出第一個奇數,然後第一個偶數和第二個奇數比較,,,依次類推,輸出多出來的奇數或偶數

#include <bits/stdc++.h>
using namespace std;
int main(){
	int t;
	cin >> t;
	while(t--){
		string s;
		cin >> s;
		int len = s.size();
		vector<int> even, odd;
		for(int i = 0; i < len; i++){
			int k = s[i] - '0';
			if((k) % 2 == 0){
				even.push_back(k);
			}
			else{
				odd.push_back(k);
			}
		}
		int i = 0, j = 0;
		while(i < even.size() && j < odd.size()){
			if(even[i] < odd[j]){
				cout << even[i];
				i++;
			}
			else{
				cout << odd[j];
				j++;
			}
		}
		while(i < even.size()){
			cout << even[i];
			i++;
		}
		while(j < odd.size()){
			cout << odd[j];
			j++;
		}
		cout << endl;
	}
	return 0;
}

D. Salary Changing(二分+思維)

題目鏈接:codeforces 1251D

題意:

    你是公司的領導,現在公司有n個人,而你手頭有s元,要給這n個人發工資,發出工資總和不能超出s,每個人都有相對應的工資區間,從k 到 r(也就是這個人最少獲得 k 元,最多獲得 r 元),求最大  發出工資的中位數。

解題思路:

    二分答案,首先將工資右區間小於 答案的劃分爲一類,它們必定在中位數的左側(取它們的左區間值,使總和儘可能小),其他的則可能在右側或者左側,將 可能在右側的數按工資左區間的大小排序,中位數右邊的數就取 max(ans, a[i].左邊界),剩下的數歸爲左側

舉例

5 26  (5個人,手頭有26元)
4 4     (第一個人最小領4元,最多領4元)
2 3
6 8
5 6
2 7

如果此時ans = 4,那麼第二個人必定在 4 的左側,其他人則先放在右側,右側的人工資 發 max(他們工資的左邊界, 4),右半邊發完剩下的人歸爲左半邊,他們 的工資爲 他們的左邊界

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
typedef long long ll;
pair<ll, ll> a[maxn];
ll n, s;
bool check(ll mid){
	ll sum = 0;
	vector<pair<ll, ll>> v;
	for(ll i = 1; i <= n; i++){
		if(a[i].second < mid){
			sum += a[i].first;
		}
		else{
			v.push_back(a[i]);
		}
	}
	ll len = v.size();
	if(len < n/2+1){
		return false;
	}
	sort(v.begin(), v.end());
	for(int i = 0; i < (n/2+1); i++){
		sum += max(mid, v[len-i-1].first);
	}
	for(int i = 0; i < len - (n/2+1); i++){
		sum += v[i].first;
	}

	if(sum <= s){
		return true;
	}
	else{
		return false;
	}
}
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		scanf("%lld%lld", &n, &s);
		for(int i = 1; i <= n; i++){
			scanf("%lld%lld", &a[i].first, &a[i].second);
		}
		ll l = 0, r = s;
		while(l != r){
			ll mid = (l + r + 1) / 2;
			if(check(mid)){
				l = mid;
			}
			else{
				r = mid - 1;
			}
		}
		printf("%lld\n", l);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章