Codeforces 551E GukiZ and GukiZiana
[传送门]
分块,每一块维护一个单调递增的数组$w$,修改时因为区间加不会影响相邻元素的大小关系,所以在对于一整块的区间加打标记就行了。若不在同一块内就暴力修改每一个数,重新维护一次$w$数组,每次修改最多需要重构两块。查询操作先对每一块的$w$数组二分看存不存在$y$,最优解肯定由第一次出现$y$的块和最后一次出现$y$的块产生,然后再暴力统计这两块的$a$数组对应$y$的位置就可以了。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 5e5 + 7; int l[N], r[N], belong[N], block, num, n, q; ll a[N], w[N], add[N]; void build() { block = sqrt(n); num = n / block; if (n % block) num++; for (int i = 1; i <= num; i++) l[i] = (i - 1) * block + 1, r[i] = i * block; r[num] = n; for (int i = 1; i <= num; i++) { for (int j = l[i]; j <= r[i]; j++) { w[j] = a[j]; belong[j] = i; } sort(w + l[i], w + r[i] + 1); } } void update(int x, int y, ll val) { int p = belong[x], q = belong[y]; if (p == q) { for (int i = x; i <= y; i++) a[i] += val; for (int i = l[p]; i <= r[p]; i++) w[i] = a[i]; sort(w + l[p], w + r[p] + 1); return; } for (int i = p + 1; i < q; i++) add[i] += val; for (int i = x; i <= r[p]; i++) a[i] += val; for (int i = l[p]; i <= r[p]; i++) w[i] = a[i]; sort(w + l[p], w + r[p] + 1); for (int i = l[q]; i <= y; i++) a[i] += val; for (int i = l[q]; i <= r[q]; i++) w[i] = a[i]; sort(w + l[q], w + r[q] + 1); } int query(ll val) { int block1 = 1e6, block2 = 0; for (int i = 1; i <= num; i++) { int pos = lower_bound(w + l[i], w + r[i] + 1, val - add[i]) - w; if (pos >= l[i] && pos <= r[i] && w[pos] == val - add[i]) { block1 = min(block1, i); block2 = max(block2, i); } } if (block2 == 0) return -1; //cout << block1 << ' ' << block2 << '\n'; int pos1 = 1e6, pos2 = 0; for (int i = l[block1]; i <= r[block1]; i++) if (a[i] + add[block1] == val) { pos1 = min(pos1, i); pos2 = max(pos2, i); } for (int i = l[block2]; i <= r[block2]; i++) if (a[i] + add[block2] == val) { pos1 = min(pos1, i); pos2 = max(pos2, i); } return pos2 - pos1; } int main() { scanf("%d%d", &n, &q); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); build(); while (q--) { int opt; scanf("%d", &opt); if (opt == 1) { int l, r; ll x; scanf("%d%d%lld", &l, &r, &x); update(l, r, x); } else { ll val; scanf("%lld", &val); printf("%d\n", query(val)); } } return 0; }

浙公网安备 33010602011771号