AT coder 380

27hhhh發表於2024-11-22

A

題目:六個數字中是否滿足1有1個,2有兩個,三有三個;

模擬

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
map<int, int> ma;
int n,flag;

void ac() {
	cin >> n;

	while (n) {
		int cnt = n % 10;
		ma[cnt]++;
		n /= 10;
	}
	if (ma[1]==1 && ma[2]== 2 && ma[3] == 3) cout << "Yes" << endl;
	else cout << "No" << endl;
}

B

題目:長度為N的串,首項為“|”,之後是根據陣列A的每一項的數字新增對應得*號之後新增一個‘|’,求A陣列;

模擬

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
map<int, int> ma;
int n,flag;
string s;
void ac() {
	cin >> s;
	int ans = 0;
	for (int i = 1; i < s.size(); i++) {
		if (s[i] == '-') {
			ans++;
		}
		if (s[i] == '|') {
			cout << ans << " ";
			ans = 0;
		}
	}
}

C

題目:給定一個01字串,連續得1組成一個塊,輸出將m塊字元移動到n塊字元後的字串

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
map<int, int> ma;
int n,k;
string s;
void ac() {
	cin >> n >> k >> s;
	int l1=0,l = 0, r = 0, cnt = 0,flag=0;
	for (int i = 0; i < n; i++) {
		if (s[i] == '1' && !flag) {
			cnt++;//記錄塊數
			if (cnt == k) {//找到了第m塊
				l = i;
				break;
			}
			flag = 1;
		}
		if (s[i] == '0' && flag) {
			flag = 0;
			if (cnt == k - 1) {//找到了第n塊;
				l1 = i;
			}
		}
	}
	cnt = l - l1;//n塊結尾到m塊開頭得距離;
	for (int i = l; i < n; i++) {
		if (s[i] == '0') break;
		else {
			swap(s[i], s[i - cnt]);//交換字元(距離與cnt相同,直到m塊結尾)
		}
	}
	cout << s;
}

D

題目:給定一個字串S,將其大小寫反轉得到字串T,將他加入S後面得到新的字串S,再重複這個步驟10^100次,問第i個字元是什麼

分析:透過模擬字串步驟發現,在原字串大小為一塊,初始為0,在塊數的二進位制中1的個數為偶,是原字串,反之是反轉後的字串,所以只用找出i位於哪個塊中即可得到該處字元的答案;

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5+5;
string s;
ll q,k;

ll sum1(ll x) {//找二進位制1的個數
	ll res = 0;
	while(x) {
		if (x % 2 == 1) {
			res++;
		}
		x /= 2;
	}
	return res;
}

void ac() {
	cin >> s >> q;
	ll cnt = s.size();
	while (q--) {
		cin >> k;
		k--;
		ll c = k % cnt;//找出k位於原字串的位置
		ll wei = 0;
		//cout << c<<" " << s[c] << endl;
		if (k >= cnt) 
			wei = k / cnt;//找到k在哪個字串塊裡;
		ll x = sum1(wei);
		//cout << x << endl;
		if (x%2==0) {
			cout << s[c] << " ";
		}
		else {
			if (s[c] >= 'a' && s[c] <= 'z') {
				printf("%c ", s[c] - 'a' + 'A');
			}
			else if (s[c] >= 'A' && s[c] <= 'Z') {
				printf("%c ", s[c] - 'A' + 'a');
			}
		}
	}
}

E

題目:一行有N個單元格i與i+1相鄰,i被塗上第i種顏色,有兩種操作1.(1 x c)將以下單元格重新塗成顏色c:透過重複移動到與當前單元格相同顏色的相鄰單元格,從單元格x到達的所有可到達單元格(相鄰的塊才能顏色相同可以合併為一個塊,被一起染色)2.(2 c)輸出c顏色的塊數;

分析:並查集合並,考慮合併的格子是否相鄰,相鄰則合併為一個塊,一起變色

ll n, q, f[N], ans[N],C[N],si[N],a, x, c;

ll find(ll x) {
	return f[x] == x ? x : f[x] = find(f[x]);
}
void marge(ll x, ll y) {
	ll fx = find(x), fy = find(y);
	if (fx == fy) return;
	if (fx > fy)swap(fx, fy);//保證是小的數是根節點
	f[fy] = fx;
	si[fx] += si[fy];
}

void ac() {
	cin >> n >> q;
	for (int i = 1; i <= n; i++) ans[i] = 1,f[i]=i,C[i]=i,si[i]=1;//ans記錄第i種顏色的塊數,f:並查集合並陣列,si:記錄合併後的塊數,C:顏色
	while (q--) {
		cin >> a;
		if (a == 1) {
			cin >> x >> c;
			x = find(f[x]);//找到根節點
			ans[C[x]] -= si[x];//根節點塊數減去將被染色的塊
			ans[c] += si[x];
			C[x] = c;//該點變色
			if (C[find(x + si[x])] == c) marge(x, x + si[x]);//該塊的與後面的塊相鄰
			if (C[find(x - 1)] == c) marge(x - 1, x);//與前面相鄰
		}
		else {
			cin >> c;
			cout << ans[c] << endl;
		}
	}
}

相關文章