1 条题解
-
0
首先做区间加区间 :
分块,块内维护 OV。
区间加时对块打 tag,块内相对大小不变。散块暴力重构,归并加的序列和每加的序列。
块长 ,复杂度 。然后,区间加区间 th:
直接二分然后用上面的东西判断是 的。
观察零散块查询的暴力是 ,整块的查询是 的。
零散块的暴力显然可以优化,预先排序(归并)之后二分查询,复杂度是 的。
这样平衡就变成了 。取块长 ,复杂度 。const int maxn = 1e5, bs = 2.5e3, nb = maxn / bs + 1; #define blk(x) (((x)-1)/bs) #define hob(x) ((x)*bs+1) #define eob(x) min(((x)+1)*bs,n) int a[maxn + 10]; int ovi[maxn + 10], tag[nb + 10], buf1[bs + 10], buf2[bs + 10], n; int tmp[bs * 2 + 10], ed; void add(int l, int r, int c) { int lb = blk(l), rb = blk(r); if(lb == rb) { rep(i,l,r) a[i] += c; // merge sort O(x) int e1 = -1, e2 = -1, p1 = 0, p2 = 0; rep(i,hob(lb),eob(lb)) if(ovi[i] >= l && ovi[i] <= r) buf1[++ e1] = ovi[i]; else buf2[++ e2] = ovi[i]; rep(i,hob(lb),eob(lb)) if(p2 > e2 || p1 <= e1 && a[buf1[p1]] < a[buf2[p2]]) ovi[i] = buf1[p1 ++]; else ovi[i] = buf2[p2 ++]; return ; } rep(i,lb + 1, rb - 1) tag[i] += c; rep(i,l,eob(lb)) a[i] += c; rep(i,hob(rb),r) a[i] += c; // merge sort O(x) int e1 = -1, e2 = -1, p1 = 0, p2 = 0; rep(i,hob(lb),eob(lb)) if(ovi[i] >= l && ovi[i] <= r) buf1[++ e1] = ovi[i]; else buf2[++ e2] = ovi[i]; rep(i,hob(lb),eob(lb)) if(p2 > e2 || p1 <= e1 && a[buf1[p1]] < a[buf2[p2]]) ovi[i] = buf1[p1 ++]; else ovi[i] = buf2[p2 ++]; // merge sort O(x) e1 = e2 = -1, p1 = p2 = 0; rep(i,hob(rb),eob(rb)) if(ovi[i] >= l && ovi[i] <= r) buf1[++ e1] = ovi[i]; else buf2[++ e2] = ovi[i]; rep(i,hob(rb),eob(rb)) if(p2 > e2 || p1 <= e1 && a[buf1[p1]] < a[buf2[p2]]) ovi[i] = buf1[p1 ++]; else ovi[i] = buf2[p2 ++]; } void prework(int l, int r) { int lb = blk(l), rb = blk(r); int e1 = -1, e2 = -1, p1 = 0, p2 = 0; ed = -1; if(lb == rb) { rep(i,hob(lb),eob(rb)) if(ovi[i] >= l && ovi[i] <= r) tmp[++ ed] = ovi[i]; } else { rep(i,hob(lb),eob(lb)) if(ovi[i] >= l && ovi[i] <= r) buf1[++ e1] = ovi[i]; rep(i,hob(rb),eob(rb)) if(ovi[i] >= l && ovi[i] <= r) buf2[++ e2] = ovi[i]; while(p1 <= e1 || p2 <= e2) { if(p2 > e2 || p1 <= e1 && a[buf1[p1]] + tag[lb] < a[buf2[p2]] + tag[rb]) tmp[++ ed] = buf1[p1 ++]; else tmp[++ ed] = buf2[p2 ++]; } } } int calc(int l, int r, int c) { // \sum [a[i]] < c * c int lb = blk(l), rb = blk(r); int ans = 0; rep(i, lb + 1, rb - 1) { int l = hob(i), r = eob(i); if(a[ovi[l]] + tag[i] >= c) continue; while(l < r) { int mid = (l + r + 1) >> 1; if(a[ovi[mid]] + tag[i] < c) l = mid; else r = mid - 1; } ans += l - hob(i) + 1; } if(~ed && a[tmp[0]] + tag[blk(tmp[0])] < c) { int l = 0, r = ed; while(l < r) { int mid = (l + r + 1) >> 1; if(a[tmp[mid]] + tag[blk(tmp[mid])] < c) l = mid; else r = mid - 1; } ans += l + 1; } return ans; } int main() { int m; scanf("%d %d", &n, &m); rep(i,1,n) scanf("%d", a + i), ovi[i] = i; rep(i,blk(1),blk(n)) sort(ovi + hob(i), ovi + eob(i) + 1, [&](int x, int y) { return a[x] < a[y]; }); int opt, l, r; int c; rep(qr,1,m) { scanf("%d %d %d %d", &opt, &l, &r, &c); if(opt == 2) { add(l, r, c); } else { if(c > r - l + 1) putchar('-'), putchar('1'), putchar('\n'); else { int rl = -2e9, rr = 2e9; prework(l, r); while(rl < rr) { int rmid = (rl + rr + 1) >> 1; if(calc(l, r, rmid) <= c - 1) rl = rmid; else rr = rmid - 1; } printf("%d\n", rl); } } } return 0; }
- 1
信息
- ID
- 4282
- 时间
- 2000ms
- 内存
- 128MiB
- 难度
- 6
- 标签
- 递交数
- 16
- 已通过
- 3
- 上传者