线段树
慢慢更新,之后加上思路解析等~~~~
1. 签到快签道
- 线段树维护:区间的最小值
#include <bits/stdc++.h> using namespace std; const int N = 100010; #define ls u<<1 #define rs u<<1|1 struct node { int l, r; int v; } tr[N << 2]; int n, q; int a[N]; void pushup(int u) { tr[u].v = min(tr[ls].v, tr[rs].v); } void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) { tr[u].v = a[l]; return ; } int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } int query(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) return tr[u].v; int mid = tr[u].l + tr[u].r >> 1; int ans = 0x7fffffff; if(l <= mid) ans = min(ans, query(ls, l, r)); if(r > mid) ans = min(ans, query(rs, l, r)); return ans; } int main() { cin >> n >> q; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); while(q--) { int l, r; cin >> l >> r; int res = 0x7fffffff; if(l != 1) res = query(1, 1, l - 1); if(r != n) res = min(res, query(1, r + 1, n)); cout << res << endl; } return 0; }
2. XOR的艺术
传送门
线段树维护:区间的 1 {1}1 的个数
#include <bits/stdc++.h> using namespace std; const int N = 200010; #define ls u<<1 #define rs u<<1|1 struct node { int l, r; int v, add; } tr[N << 2]; int a[N]; void pushup(int u) { tr[u].v = tr[ls].v + tr[rs].v; } void pushdown(int u) { if(tr[u].add) { tr[u].add ^= 1; tr[ls].add ^= 1, tr[rs].add ^= 1; tr[ls].v = (tr[ls].r - tr[ls].l + 1) - tr[ls].v; tr[rs].v = (tr[rs].r - tr[rs].l + 1) - tr[rs].v; } } void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) { tr[u].v = a[l] == 1 ? 1 : 0; return ; } int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } int query(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) return tr[u].v; int mid = tr[u].l + tr[u].r >> 1; pushdown(u); int ans = 0; if(l <= mid) ans = query(ls, l, r); if(r > mid) ans += query(rs, l, r); return ans; } void modify(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) { tr[u].add ^= 1; tr[u].v = (tr[u].r - tr[u].l + 1) - tr[u].v; return ; } pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) modify(ls, l, r); if(r > mid) modify(rs, l, r); pushup(u); } int main() { int n, m, p, l, r; cin >> n >> m; string s; cin >> s; for(int i = 0; i < n; i++) a[i + 1] = s[i] - '0'; build(1, 1, n); for(int i = 1; i <= m; i++) { cin >> p >> l >> r; if(p == 0) modify(1, l, r); if(p == 1) cout << query(1, l, r) << endl; } return 0; }
3. 魔法学院(easy version)
- 线段树维护:区间的最大值,区间推平。
#include <bits/stdc++.h> using namespace std; const int N = 200010; #define ls u<<1 #define rs u<<1|1 struct Node { int l, r, c; bool operator<(const Node& A) const { return c < A.c; } } op[N]; struct node { int l, r; int v; } tr[N << 2]; int n, q, l, r, c; string s; void pushdown(int u) { tr[ls].v = max(tr[ls].v, tr[u].v); tr[rs].v = max(tr[rs].v, tr[u].v); } void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) { tr[u].v = s[l]; return ; } int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); } int query(int u, int x) { if(tr[u].l >= x && tr[u].r <= x) return tr[u].v; int mid = tr[u].l + tr[u].r >> 1; pushdown(u); int res = 0; if(x <= mid) return query(ls, x); return query(rs, x); } void modify(int u, int l, int r, int c) { if(tr[u].l >= l && tr[u].r <= r) { tr[u].v = max(tr[u].v, c); return ; } int mid = tr[u].l + tr[u].r >> 1; pushdown(u); if(l <= mid) modify(ls, l, r, c); if(r > mid) modify(rs, l, r, c); } int main() { cin >> n >> q; cin >> s; s = '#' + s; for (int i = 0; i < q; i++) { cin >> op[i].l >> op[i].r; char c; cin >> c; op[i].c = c; } sort(op, op + q); build(1, 1, n); for (int i = 0; i < q; i++) modify(1, op[i].l, op[i].r, op[i].c); int res = 0; for (int i = 1; i <= n; i++) { res += query(1, i); } cout << res << endl; return 0; }
- 并查集(魔法学院(hard version))
#include <bits/stdc++.h> using namespace std; const int N = 10000010; char s[N]; int a[N]; int n, m; vector<pair<int, int>> q[127]; int fa[N]; int find(int x) { return fa[x] = fa[x] == x ? x : find(fa[x]); } int main() { scanf("%d%d", &n, &m); scanf("%s", s + 1); for (int i = 0; i <= n; i++) fa[i] = i; int l, r; char c; while(m--) { scanf("%d%d %c", &l, &r, &c); q[c].push_back({l, r}); } for (int i = 126; i >= 33; i--) { for (int j = 0; j < q[i].size(); j++) { l = q[i][j].first, r = q[i][j].second; for (int k = find(r); k >= l; k = find(k)) { s[k] = max(s[k], (char)i); fa[k] = find(k - 1); } } } long long ans = 0; for (int i = 1; i <= n; i++) ans += s[i]; printf("%d\n", ans); return 0; }
4. E - Meaningful Mean
- 线段树维护:区间值之和。
#include <bits/stdc++.h> using namespace std; #define ls u<<1 #define rs u<<1|1 #define int long long const int N = 250010; struct node { int l, r; int v; } tr[N << 2]; int n, k, a[N], b[N]; void pushup(int u) { tr[u].v = tr[ls].v + tr[rs].v; } void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) return ; int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); } int query(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) return tr[u].v; int mid = tr[u].l + tr[u].r >> 1; int ans = 0; if(l <= mid) ans = query(ls, l, r); if(r > mid) ans += query(rs, l, r); return ans; } void modify(int u, int x, int v) { if(tr[u].l >= x && tr[u].r <= x) { tr[u].v += v; return ; } int mid = tr[u].l + tr[u].r >> 1; if(x <= mid) modify(ls, x, v); else modify(rs, x, v); pushup(u); } signed main() { cin >> n >> k; for (int i = 1; i <= n; i++) cin >> a[i], a[i] -= k; a[0] -= k; for (int i = 1; i <= n; i++) a[i] += a[i - 1], b[i] = a[i]; b[0] = a[0]; sort(a, a + 1 + n); for (int i = 0; i <= n; i++) b[i] = lower_bound(a, a + 1 + n, b[i]) - a; build(1, 0, n); int res = 0; // sum(r) >= sum(l - 1) for (int i = 1; i <= n; i++) { modify(1, b[i - 1], 1); res += query(1, 0, b[i]); } cout << res << endl; return 0; }
5. 干饭得插队
- 线段树维护:区间值之和。
#include <bits/stdc++.h> using namespace std; #define ls u<<1 #define rs u<<1|1 const int N = 1000010; struct node { int l, r; int v; } tr[N << 2]; struct Node { int id, val; } a[N]; int n, k; int ans[N]; int len(int u) { return tr[u].r - tr[u].l + 1; } void pushup(int u) { tr[u].v = tr[ls].v + tr[rs].v; } void build(int u, int l, int r) { tr[u] = {l, r}; if(l == r) return ; int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); } void modify(int u, int x, int v) { if(tr[u].l == tr[u].r) { tr[u].v += 1; ans[tr[u].l] = v; return ; } if(x <= len(ls) - tr[ls].v) modify(ls, x, v); else modify(rs, x + tr[ls].v - len(ls), v); pushup(u); } int main() { cin >> n; for (int i = 1; i <= n; i++) cin >> a[i].id >> a[i].val; build(1, 1, n); for (int i = n; i >= 1; i--) { int id = a[i].id + 1, val = a[i].val; modify(1, id, val); } for (int i = 1; i <= n; i++) cout << ans[i] << ' '; return 0; }
6. 割韭菜
待补!!!
https://ac.nowcoder.com/acm/contest/30825/A
7. Rooks Defenders
- 板子,区间修改,区间查询
#include <bits/stdc++.h> using namespace std; #define ls u<<1 #define rs u<<1|1 #define int long long const int N = 250000; struct node{ int l, r; int sum, add; }tr[N << 2]; int a[N]; int n, m; void pushup(int u) { tr[u].sum = tr[ls].sum + tr[rs].sum; } int len(int u) { return tr[u].r - tr[u].l + 1; } void pushdown(int u) { if(tr[u].add) { tr[ls].sum = tr[u].add * len(ls); tr[rs].sum = tr[u].add * len(rs); tr[ls].add = tr[u].add; tr[rs].add = tr[u].add; tr[u].add = 0; } } void build(int u, int l, int r) { tr[u] = {l, r, 0, 0}; if(l == r) { tr[u].sum = a[l]; tr[u].add = 0; return ;} int mid = l + r >> 1; build(ls, l, mid), build(rs, mid + 1, r); pushup(u); } void modify(int u, int l, int r, int x) { if (tr[u].l >= l && tr[u].r <= r) { tr[u].sum = len(u) * x; tr[u].add = x; return ; } pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if(l <= mid) modify(ls, l, r, x); if(r > mid) modify(rs, l, r, x); pushup(u); } int query(int u, int l, int r) { if(tr[u].l >= l && tr[u].r <= r) { return tr[u].sum; } int mid = tr[u].l + tr[u].r >> 1; int v = 0; pushdown(u); if(l <= mid) v = query(ls, l, r); if(r > mid) v += query(rs, l, r); return v; } signed main() { cin >> n >> m; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); int op, x, v; while(m--) { cin >> op; if(op == 1) { cin >> x >> v; modify(1, x, x, v); } else { cin >> x; modify(1, 1, n, x); } cout << query(1, 1, n) << endl; } return 0; }