C. Canine poetry
時間:2024-07-05
原題:Good Bye 2020 C. Canine poetry
題意
對於一個字串 \(s\) ,可以對任一字元變為 \(*\) 號,使所有子串不為迴文串,即可將 \(babba\) 變為 \(ba*ba\) 使字串內不存在迴文串
資料範圍: \(|s|\le 1e5\)
思路
對於某迴文字串,如果是長度為奇數,那麼中心的三個字元組成的子串一定是字串,偶數同理
那麼將所有的長度為2和3的迴文串進行處理就能達到效果
程式碼
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long
int _, n;
vector<bool>vis;
void solve() {
string s;
cin >> s;
int len = s.length();
vis.assign(len, false);
int ans = 0;
for (int i = 1; i < s.length(); i++) {
// 長度為2的迴文串,如果沒被換過,換後面的字元
if (s[i] == s[i - 1] && !vis[i - 1]) {
vis[i] = true;
ans++;
}
// 長度為3的迴文串,同理換第一個
else if (i - 2 >= 0 && s[i] == s[i - 2] && !vis[i - 2]) {
vis[i] = true;
ans++;
}
}
cout << ans << endl;
}
signed main() {
cin >> _;
while (_--)
solve();
return 0;
}
C. Ehab and Path-etic MEXs
時間:2024-07-05
原題:Codeforces Round 628 (Div. 2) C. Ehab and Path-etic MEXs
題意
有一顆 \(n\) 個結點的樹,對每條邊編號,屬於 \([0,n-2]\) ,要求所有對節點對 \((u,v)\) ,其 \(MEX(u,v)\) 的最大值最小
\(MEX(u,v)\) 表示從 \(u\) 到 \(v\) 的唯一簡單路徑上沒出現過的最小編號
理解: 有點繞,就是說,有從 \(u\) 到 \(v\) 假如經過了邊1,2,4那麼最小的未出現的數就是0,則 \(MEX(u,v)=0\)
即 \(Ans=max(MEX(u,v))\) ,求 \(Ans_{min}\)
思路
首先假定是最簡單的情況,也就是一條鏈,那麼簡單看一下所有的可能性,可知 \(Ans=n-1\)
所以對於單鏈,隨機存放即可
接下來,如果多了一條鏈,那麼可以觀察度大於等於3的點
對於這樣的點,無論哪種 \((u,v)\) 的搭配,對於這個點至少有一條邊不被覆蓋
即只要將0,1,2這最小的三個編號分配在三條分路上,其他編號隨意分配,就能實現 \(Ans=2\)
程式碼
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define int long long
#define rep(i,j,k) for(i=(j);i<(k);i++)
typedef pair<int, int> pii;
const int N = 1e5 + 10;
int n, ii;
vector<vector<int>>g;
int u[N], v[N];
void solve() {
cin >> n;
g.assign(n + 1, vector<int>(0));
rep(ii, 0, n - 1) {
cin >> u[ii] >> v[ii];
g[u[ii]].emplace_back(v[ii]);
g[v[ii]].emplace_back(u[ii]);
}
// 如果有大於等於3的度,以儲存兩個頂點的形式儲存每條邊,012對應共三條
pii p[3];
int i;
for (i = 0; i < g.size(); i++) {
vector<int> vv = g[i];
if (vv.size() >= 3) {
for (int j = 0; j < 3; j++) {
p[j].first = i;
p[j].second = vv[j];
}
break;
}
}
// 如果沒有大於等於3的度,隨意輸出
if (i == g.size()) {
rep(ii, 0, n - 1) {
cout << ii << endl;
}
return;
}
int ans = 0;
int index = 3;
for (int i = 0; i < n - 1; i++) {
int j;
for (j = 0; j < 3; j++) {
int f = p[j].first, s = p[j].second;
// 如果是012所在的邊,輸出012,否則輸出index
if ((u[i] == f && v[i] == s) || (u[i] == s && v[i] == f)) {
cout << ans << endl;
ans++;
break;
}
}
if (j == 3) {
cout << index++ << endl;
}
}
}
signed main() {
solve();
return 0;
}