## Spring Practices 05 心得&題解
[<<回主頁](https://hackmd.io/@r1cky/Sk2hKzga6)
### 前言
因為是學校練習用的,不知道題目能不能公開,但還是寫個心得好了。
總共有五題,編號 A~E,以下照 AC 順序:
要 midterm 了 QQ
### pA
首先注意到,如果一個字串裡有 `00` `11` 這種字串肯定是回文的,如果有 `010` `101` 這種也是不行的,那我們會發現當字串長度 > 3 一定無解,在 字串長度 2 以下的 case 很少,就判一下即可。
```cpp=
// Author : rickytsung
// Problem :
// Date :
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pii pair<int, int>
#define f first
#define s second
#define pb(x) push_back(x)
using namespace std;
mt19937 rng(114514);
const int mod1 = 998244353;
int rnd(int l, int r) {
return uniform_int_distribution<int>(l, r)(rng);
}
i64 gcd(i64 a,i64 b){
if (a%b == 0) return(b);
else return(gcd(b, a%b));
}
i64 lcm(i64 a, i64 b){
return a/gcd(a, b) * b;
}
int main() {
IOS;
int t, n;
string s;
cin >> t;
while(t--){
cin >> n >> s;
if(s == "0" || s == "1" || s == "01" || s == "10"){
cout << "YES\n";
}
else{
cout << "NO\n";
}
}
}
```
### pB
因為題目 k 只有 10,所以我們可以窮舉 $n$ 以上的數去看他符不符合,窮舉 20 個以內一定會找到一個符合題目條件的。
時間複雜度 $O(t \cdot 20)$
``` cpp=
// Author : rickytsung
// Problem :
// Date :
#pragma GCC optimize("O3,unroll-loops")
#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define i128 __int128
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pii pair<int, int>
#define f first
#define s second
#define pb(x) push_back(x)
using namespace std;
mt19937 rng(114514);
const int mod1 = 998244353;
int rnd(int l, int r) {
return uniform_int_distribution<int>(l, r)(rng);
}
i64 gcd(i64 a,i64 b){
if (a%b == 0) return(b);
else return(gcd(b, a%b));
}
i64 lcm(i64 a, i64 b){
return a/gcd(a, b) * b;
}
int main() {
IOS;
int t, n, m;
cin >> t;
while(t--){
cin >> n >> m;
for(int i = n; ; i ++){
int op = i, bcnt = 0;
for(int j = 0; j < 10; j++){
bcnt += op % 10;
op /= 10;
}
bcnt %= m;
if(bcnt == 0){
cout << i << '\n';
break;
}
}
}
}
```
### pC
維護一個 pq,然後把所有丟進去,每次選最大的拿出來除以 2 再放回去,直到血條被扣到 0 或裡面沒東西為止,因為每個元素 log 次操作內一定會變成 0。
時間複雜度 $O(n\ log\ n\ log\ a_i)$
```cpp=
#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define i128 __int128
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pii pair<int, int>
#define f first
#define s second
#define pb(x) push_back(x)
using namespace std;
int main() {
IOS;
int t, n, x, z;
i64 ans = 0, a, b;
cin >> t;
while(t--){
cin >> n >> z;
ans = 0;
priority_queue <int> pq;
for(int i = 0; i < n; i++){
cin >> x;
pq.push(x);
}
while(pq.size() != 0 && z > 0){
a = pq.top(); pq.pop();
z -= a;
a /= 2;
ans ++;
if(a > 0) pq.push(a);
}
if(z > 0){
cout << "Evacuate\n";
}
else cout << ans << '\n';
}
}
```
### pD
先算出敵方需要幾天達到 $Z$,然後接著算出自己在那個天數減 1 後自己方有幾個人,然後需要幾個,就變成 pC ㄌㄌ。
```cpp=
// Author : rickytsung
// Problem :
// Date :
#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define i128 __int128
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pii pair<int, int>
#define f first
#define s second
#define pb(x) push_back(x)
using namespace std;
int main() {
IOS;
int t, n, u ;
i64 ans = 0, a, b, x, y, z;
cin >> t;
while(t--){
cin >> n >> a >> b >> x >> y >> z;
ans = 0;
priority_queue <int> pq;
for(int i = 0; i < n; i++){
cin >> u;
pq.push(u);
}
i64 day = (z - b - 1) / y;
i64 need = z - day * x - a;
while(pq.size() != 0 && need > 0){
a = pq.top(); pq.pop();
need -= a;
a /= 2;
ans ++;
if(a > 0) pq.push(a);
}
if(need > 0){
cout << "RIP\n";
}
else cout << ans << '\n';
}
}
```
### pE
我們對於每個團體裡的人都倆倆合併,然後注意的是如果對於一個團體裡所有數對 $(x,y)$ 都做 union 會退化成 $O(k^2)$,而其實我們只要第 i 個和第 i+1 個做 union 就好。
最後再根據各自所屬團體計算裡面有幾個。
時間複雜度 $O(n+\sum k_i \cdot α(n))$
```cpp=
#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt")
#include <bits/stdc++.h>
#define i64 long long
#define i128 __int128
#define IOS ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define pii pair<int, int>
#define f first
#define s second
#define pb(x) push_back(x)
using namespace std;
const int maxn = 5e5 + 5;
int dsu[maxn], sz[maxn];
int find(int x){
if(dsu[x] == x){
return x;
}
return dsu[x] = find(dsu[x]);
}
void onion(int f, int s){
int tx = find(f);
int ty = find(s);
dsu[tx] = ty;
}
int main() {
IOS;
int n, m, k, p, x;
cin >> n >> m;
for(int i = 1; i <= n; i++){
dsu[i] = i;
}
for(int i = 1; i <= m; i++){
cin >> k;
for(int j = 0; j < k; j++){
cin >> x;
if(j == 0) {
p = x;
continue;
}
onion(p, x);
p = x;
}
}
for(int i = 1; i <= n; i++){
sz[find(i)]++;
}
for(int i = 1; i <= n; i++){
cout << sz[find(i)] << ' ';
}
}
```