A. lz的吃飯問題
print("lz" if (lambda a,b: a*b)(*map(int, input().split())) < (lambda a,b: a*b)(*map(int, input().split())) else "gzy")
B. lz的數字問題
把數字按字串處理,找到小數點則分成整數和小數兩段;沒有小數點則整個字串都賦給整數部分,小數部分為空串。得到 \(a_1,a_2,b_1,b_2\) 四部分。把 \(a_2,b_2\) 長度補到 6,然後比較是否有 \(a_1=b_1,a_2=b_2\) 即可。
string a, b; cin >> a >> b;
// 處理數字a
int n = a.size(); string a1, a2; // 整數、小數部分
for (int i = 0; i < n; i++)
if (a[i] == '.') a1 = a.substr(0, i), a2 = a.substr(i + 1, min(n - i - 1, 6));
if (a1.empty()) a1 = a;
while (a2.size() < 6) a2 += '0';
// 處理數字 b
int m = b.size(); string b1, b2;
for (int i = 0; i < m; i++)
if (b[i] == '.') b1 = b.substr(0, i), b2 = b.substr(i + 1, min(m - i - 1, 6));
if (b1.empty()) b1 = b;
while (b2.size() < 6) b2 += '0';
// 輸出答案
cout << ((a1 == b1 && a2 == b2) ? "YES\n" :"NO\n");
C. lz的蛋撻問題
注意到對於一個位於第一行的白色格子,只有 4 種情況下,把它變黑可以增加連通塊數目:
- 右側、下方是白色,右下角是黑色;
- 左側、下方是白色,左下角是黑色;
- 左右兩邊是白色,下方是黑色;
- 左右下都是黑色。
對於第二行的格子,把“下方“改成上方即可,用二維陣列搭配 i^1
切換上下可以統一。對於邊緣的格子,可以在兩頭各加上一列黑色格子,方便處理邊界情況。
for (int i = 0; i <= 1; i++) {
scanf("%s", s[i] + 1);
s[i][0] = s[i][n + 1] = 'x';
}
int ans = 0;
for (int i = 0; i <= 1; i++) {
for (int j = 1; j <= n; j++) {
if (s[i][j] == 'x') continue;
if (s[i][j - 1] == '.' && s[i][j + 1] == '.' && s[i ^ 1][j] == 'x') ans++
else if (s[i][j + 1] == '.' && s[i ^ 1][j] == '.' && s[i ^ 1][j + 1] == 'x') ans++;
else if (s[i][j - 1] == '.' && s[i ^ 1][j] == '.' && s[i ^ 1][j - 1] == 'x') ans++;
else if (s[i][j - 1] == 'x' && s[i][j + 1] == 'x' && s[i ^ 1][j] == 'x') ans++;
}
}
printf("%d\n", ans);
D. lz的染色問題
對於 \(m\) 個詢問,用並查集維護哪些花顏色要求相同。把要求同種顏色的花取出來,求一個眾數,然後剩下的花顏色改成眾數。可以 \(O(n+m)\),但帶 \(\log\) 也能過。
int count(vector<int>& v) { // 求眾數個數
sort(v.begin(), v.end(), [&](int i, int j) { return c[i] < c[j]; }); // 排序,同種顏色的變成連續段
int mxcnt = 1, cnt = 1;
for (int i = 1; i < v.size(); i++)
if (c[v[i]] == c[v[i - 1]]) cnt += 1;
else mxcnt = max(mxcnt, cnt), cnt = 1;
return max(mxcnt, cnt); // 注意處理最後一段
}
int main() {
int n, m, ans = 0; cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> c[i], pa[i] = i;
while (m--) {
int x, y; cin >> x >> y;
int px = find(x), py = find(y);
if (px != py) pa[px] = py;
}
map<int, vector<int>> mp;
for (int i = 1; i <= n; i++) mp[find(i)].push_back(i); // 要求同種顏色的放在一起
for (auto& [i, v] : mp) ans += v.size() - count(v); // 都變成眾數最優
cout << ans << '\n';
}
E. lz的括號問題
一個括號序列可以分成幾個合法的括號序列,比如 ((()))(())
可以分成 ((()))
和 (())
。自己所在的序列之外的其它括號,顯然都可以在自己前面匹配掉;而自己所在的序列中,這個括號之間的括號都可以在它之前匹配掉。把這兩部分加起來就是該括號的答案。
更簡單的做法是在彈棧之後看看棧裡還有 \(x\) 對括號,這些括號沒法在自己之前匹配上,能匹配上的就是 \(n-x\) 對。
for (int i = 1; i <= n * 2; i++)
if (s[i] == '(') st.push(i);
else if (st.empty()) return puts("-1"), 0;
else cnt[st.top()] = st.size(), st.pop();
if (!st.empty()) return puts("-1"), 0;
for (int i = 1; i <= n * 2; i++)
if (s[i] != ')') printf("%d ", n - cnt[i]);
F. lz的序列問題
線段樹,考慮如何合併這個字首積和 \(sum\),發現可以左區間 \(sum\) + 右區間 \(sum \times\) 左區間區間積,而這兩個屬性都是支援區間賦值的——區間積直接快速冪,\(sum\) 可以用等比數列求和做。注意取模即可。
using Mod = ModInt<LL, 1000000007>; // 用了模數類
const int N = 1e5 + 10;
int n, q, a[N];
struct segtree {
int l, r;
Mod sum, prod, tag;
} t[N << 2];
#define ls p << 1
#define rs p << 1 | 1
#define mid ((t[p].l + t[p].r) >> 1)
inline Mod power(Mod a, int n); // 快速冪(略)
inline void refresh(int p) {
t[p].prod = t[ls].prod * t[rs].prod;
t[p].sum = (t[ls].sum + t[ls].prod * t[rs].sum);
}
void build(int p, int l, int r);
inline void pushup(int p, Mod v) {
t[p].tag = v;
int len = t[p].r - t[p].l + 1;
t[p].prod = power(v, len);
t[p].sum = (v == 1) ? len : (power(v, len + 1) - v) / (v - 1); // 注意公比q=1時不能用公式(除0)
}
inline void pushdown(int p) {
if (t[p].tag == 0) return;
pushup(ls, t[p].tag);
pushup(rs, t[p].tag);
t[p].tag = 0;
}
void fill(int p, int l, int r, Mod v) {
if (l <= t[p].l && t[p].r <= r) return pushup(p, v), void(0);
pushdown(p);
if (l <= mid) fill(ls, l, r, v);
if (r > mid) fill(rs, l, r, v);
refresh(p);
}
Mod get_prod(int p, int l, int r) {
if (l <= t[p].l && t[p].r <= r) return t[p].prod;
pushdown(p);
Mod res = 1;
if (l <= mid) res = res * get_prod(ls, l, r);
if (r > mid) res = res * get_prod(rs, l, r);
return res;
}
Mod get_sum(int p, int l, int r) {
if (l <= t[p].l && t[p].r <= r) return t[p].sum;
pushdown(p);
if (l > mid) return get_sum(rs, l, r); // 注意不要寫反ls,rs
if (r <= mid) return get_sum(ls, l, r);
return (get_sum(ls, l, r) + get_prod(ls, l, r) * get_sum(rs, l, r));
}
int main() {
cin >> n >> q;
for (int i = 1; i <= n; i++) cin >> a[i];
build(1, 1, n);
while (q--) {
int op, l, r; Mod x;
cin >> op;
if (op == 1) {
cin >> l >> r >> x;
fill(1, l, r, x);
} else if (op == 2) {
cin >> l >> r;
cout << get_sum(1, l, r) << endl;
}
}
}