18 条题解
-
15
使用线段树,转化为区间求和问题
#include <bits/stdc++.h> #define l(x) tree[x].l #define r(x) tree[x].r #define sum(x) tree[x].sum #define add(x) tree[x].add using namespace std; struct SegmentTree { int l, r; //区间左右端点 long long sum, add; //sum 区间和 add 延迟标记 } tree[400010]; int a[100010], n = 1, m = 2; void build (int p, int l, int r) { l(p) = l, r(p) = r; if(l == r) {sum(p) = a[l]; return;} int mid = l + r >> 1; build(p * 2, l, mid); build(p * 2 + 1, mid + 1, r); sum(p) = sum(p * 2) + sum(p * 2 + 1); } void spread(int p) { if(add(p)) { //节点p有标记 sum(p * 2) += add(p) * (r(p * 2) - l(p * 2) + 1); //更新左子节点信息 sum(p * 2 + 1) += add(p) * (r(p * 2 + 1) - l(p * 2 + 1) + 1); //更新右子节点 add(p * 2) += add(p); //给左子节点打延迟标记 add(p * 2 + 1) += add(p); //给右子节点打延迟标记 add(p) = 0; //清除p的标记 } } void change(int p, int l, int r, int d) { if(l <= l(p) && r >= r(p)) { //完全覆盖 sum(p) += (long long) d * (r(p) - l(p) + 1); //更新节点信息 add(p) += d; //给节点打延迟标记 return; } spread(p); //下传延迟标记 int mid = l(p) + r(p) >> 1; if(l <= mid) change(p * 2, l, r, d); if(r > mid) change(p * 2 + 1, l, r, d); sum(p) = sum(p * 2) + sum(p * 2 + 1); } long long ask(int p, int l, int r) { if(l <= l(p) && r >= r(p)) return sum(p); spread(p); int mid = l(p) + r(p) >> 1; long long val = 0; if(l <= mid) val += ask(p * 2, l, r); if(r > mid) val += ask(p * 2 + 1, l, r); return val; } int main() { a[1] = 0; build(1, 1, n); while(m--) { int d = 0; scanf("%d", &d); change(1, 1, 1, d); } printf("%lld\n", ask(1, 1, 1)); return 0; }
树状数组
思路一样,区间求和
#include<bits/stdc++.h> using namespace std; const int SIZE = 100010; int a[SIZE], n = 1, m = 2; long long c[2][SIZE], sum[SIZE]; long long ask(int k, int x) { long long ans = 0; for(; x ; x -= x & -x) ans += c[k][x]; return ans; } void add(int k,int x,int y) { for(; x <= n; x += x & -x) c[k][x] += y; } int main() { a[1] = 0; while(m--) { int d = 0; scanf("%d", &d); add(0, 1, d); add(0, 2, -d); add(1, 1, d); add(1, 2, -2 * d); } long long ans = sum[1] + 2 * ask(0, 1) - ask(1, 1); ans -= sum[0] + 1 * ask(0, 0) - ask(1, 0); printf("%lld\n", ans); return 0; }
分块
思路一样,区间求和
#include<bits/stdc++.h> using namespace std; long long a[50000010], sum[50000010], add[50000010]; int L[50000010], R[50000010]; int pos[50000010]; int n = 1, m = 2, t; void change(int l, int r, long long d) { int p = pos[l], q = pos[r]; if (p == q) { for (int i = l; i <= r; i++) a[i] += d; sum[p] += d*(r - l + 1); } else { for (int i = p + 1; i <= q - 1; i++) add[i] += d; for (int i = l; i <= R[p]; i++) a[i] += d; sum[p] += d*(R[p] - l + 1); for (int i = L[q]; i <= r; i++) a[i] += d; sum[q] += d*(r - L[q] + 1); } } long long ask(int l, int r) { int p = pos[l], q = pos[r]; long long ans = 0; if (p == q) { for (int i = l; i <= r; i++) ans += a[i]; ans += add[p] * (r - l + 1); } else { for (int i = p + 1; i <= q - 1; i++) ans += sum[i] + add[i] * (R[i] - L[i] + 1); for (int i = l; i <= R[p]; i++) ans += a[i]; ans += add[p] * (R[p] - l + 1); for (int i = L[q]; i <= r; i++) ans += a[i]; ans += add[q] * (r - L[q] + 1); } return ans; } int main() { a[1] = 0; t = sqrt(n*1.0); for (int i = 1; i <= t; i++) { L[i] = (i - 1)*sqrt(n*1.0) + 1; R[i] = i*sqrt(n*1.0); } if (R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n; for (int i = 1; i <= t; i++) for (int j = L[i]; j <= R[i]; j++) { pos[j] = i; sum[i] += a[j]; } while (m--) { int d; scanf("%d", &d); change(1, 1, d); } printf("%lld\n", ask(1, 1)); }
这样我们就
完美的解决掉了这道难题 -
3
这什么gui题!
写的是:
提示
对于100%的数据,输入的整数在int的范围内。
实际是:
#include <bits/stdc++.h> int main(){ int n, m; scanf("%d%d", &n, &m); printf("%d", n + m); return 0; }
AC:5,WA:5......
#include <bits/stdc++.h> int main(){ long long n, m; scanf("%lld%lld", &n, &m); printf("%lld", n + m); return 0; }
AC:10
Tom老师,改改提示!
- 1
信息
- ID
- 116
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 8
- 标签
- 递交数
- 24873
- 已通过
- 3274
- 上传者