void solve() {
cin >> n >> t.aa >> t.bb;
for (int i = 0; i < n; i ++) cin >> a[i].aa >> a[i].bb;
sort(a, a + n);
a[n] = {a[0].aa + 24, a[0].bb};
int l = 0, r = n;
while (l < r) {
int mid = l + r >> 1;
if (t.aa < a[mid].aa || t.aa == a[mid].aa && t.bb <= a[mid].bb) r = mid;
else l = mid + 1;
}
int h = a[l].aa - t.aa, w = a[l].bb - t.bb;
if (w < 0) h --, w += 60;
cout << h << ' ' << w << endl;
}
int solve() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
set<int> st;
for (int i = n - 1; i >= 0; i --) {
if (st.count(a[i])) return i + 1;
st.insert(a[i]);
}
return 0;
}
string solve() {
cin >> n;
string ans;
int t = 9;
while (n) {
if (n > t) ans += char('0' + t), n -= t --;
else ans += char('0' + n), n = 0;
}
reverse(ans.begin(), ans.end());
return ans;
}
区间覆盖问题,每次找能与左边已选的区间接轨,并且贪心地选择尽可能往右延申的区间
int n, m;
string t, s[M];
void solve() {
cin >> t >> m;
n = t.size();
for (int i = 0; i < m; i ++) cin >> s[i];
vector<pii> e[n + 1];
for (int i = 0; i < n; i ++)
for (int j = 0; j < m; j ++) {
if (i + s[j].size() - 1 >= n) continue;
if (t.substr(i, s[j].size()) == s[j]) e[i].emplace_back(i + s[j].size() - 1, j);
}
vector<pii> ans;
int l = -1, r = -1;
while (r < n - 1) {
pii t;
t.aa = t.bb = -1;
for (int i = l + 1; i <= r + 1; i ++)
for (auto j : e[i]) t = max(t, j);
if (t.aa < 0) {
cout << -1 << endl;
return;
}
r = t.aa, l = r - s[t.bb].size() + 1;
ans.emplace_back(t.bb + 1, l + 1);
}
cout << ans.size() << endl;
for (auto [x, y] : ans) cout << x << ' ' << y << endl;
}
只存在 0 或 5,5 先 +5,判断是否全一致
其他奇数先 ×2,只剩偶数
偶数分两类,循环节是 20,只能存在一类偶数
int n, m;
int a[N];
string solve() {
cin >> n;
for (int i = 0; i < n; i ++) cin >> a[i];
int cnt0 = 0, cnt5 = 0, cnt = 0, Max = 0;
for (int i = 0; i < n; i ++) {
if (a[i] % 10 == 0) cnt0 ++;
else if (a[i] % 5 == 0) cnt5 ++, a[i] += 5;
else if (a[i] & 1) a[i] = (a[i] + a[i] % 10) % 20, cnt ++;
else a[i] %= 20, cnt ++;
if (a[i] > a[Max]) Max = i;
}
if (cnt0 + cnt5 && cnt) return no;
if (cnt0 + cnt5) {
for (int i = 1; i < n; i ++)
if (a[i] != a[i - 1]) return no;
return yes;
}
for (int i = 0; i < n; i ++)
if (a[i] == 14 || a[i] % 3 == 0) cnt --;
if (!cnt || cnt == n) return yes;
return no;
}
有两种情况,一种是一个点在另外连个点形成的路径上
另一种是三个点从一个根延申出去
int n, m;
int d12, d23, d31;
int idx;
void f(int u, int v, int w) {
cout << u << ' ' << (w == 1 ? v : idx) << endl;
for (int i = 0; i < w - 2; i ++, idx ++) cout << idx << ' ' << idx + 1 << endl;
if (w != 1) cout << idx ++ << ' ' << v << endl;
}
void solve() {
cin >> n >> d12 >> d23 >> d31;
if (d12 + d23 < d31 || d12 + d31 < d23 || d23 + d31 < d12 || (d12 + d23 + d31) & 1) {
cout << no << endl;
return;
}
if (d12 + d23 == d31 || d12 + d31 == d23 || d23 + d31 == d12) {
cout << yes << endl;
idx = 4;
if (d12 + d23 == d31) f(1, 2, d12), f(2, 3, d23);
if (d12 + d31 == d23) f(2, 1, d12), f(1, 3, d31);
if (d23 + d31 == d12) f(2, 3, d23), f(3, 1, d31);
} else {
int s = d12 + d23 + d31 >> 1;
int d1 = s - d23, d2 = s - d31, d3 = s - d12;
if (d1 <= 0 || d2 <= 0 || d3 <= 0 || d1 + d2 + d3 >= n) {
cout << no << endl;
return;
}
cout << yes << endl;
idx = 5;
f(1, 4, d1), f(2, 4, d2), f(3, 4, d3);
}
while (idx <= n) cout << 1 << ' ' << idx ++ << endl;
}
树上前缀和
int n, m;
ll A[N], B[N];
int ans[N];
int cnt;
struct Node { int v, a, b; };
vector<vector<Node>> e(N);
void dfs(int u = 1, int fa = 0) {
for (auto [v, a, b] : e[u]) {
if (v == fa) continue;
A[v] = A[u] + a;
B[cnt + 1] = B[cnt] + b;
cnt ++;
ans[v] = upper_bound(B + 1, B + cnt + 1, A[v]) - B - 1;
dfs(v, u);
cnt --;
}
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i ++) e[i].clear();
for (int i = 2; i <= n; i ++) {
int p, a, b; cin >> p >> a >> b;
e[p].push_back({i, a, b});
}
cnt = 0;
dfs();
for (int i = 2; i <= n; i ++) cout << ans[i] << ' ';
cout << endl;
}