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