题目链接:传送门 区间加法,询问x的前驱
这个有的做法也有
的做法
下面是
太懒啦~~
修改的时候把中的原数删掉
加上之后再放进去
查询的时候符合要求的才算进答案
lower_bound那块地方可以自己手推琢磨一下
/**
* @Date: 2019-03-16T19:54:04+08:00
* @Last modified time: 2019-03-16T19:54:04+08:00
*/
#include <bits/stdc++.h>
#define
using namespace std;
int n, m, f[A], sq[A], bl[A], opt, a, b, c;
set<int> s[A];
void add(int a, int b, int c) {
for (int i = a; i <= min(bl[a] * m, b); i++)
s[bl[a]].erase(sq[i]), sq[i] += c, s[bl[a]].insert(sq[i]);
if (bl[a] != bl[b])
for (int i = (bl[b] - 1) * m + 1; i <= b; i++)
s[bl[b]].erase(sq[i]), sq[i] += c, s[bl[b]].insert(sq[i]);
for (int i = bl[a] + 1; i <= bl[b] - 1; i++) f[i] += c;
}
int ask(int a, int b, int c, int ans = -1) {
for (int i = a; i <= min(bl[a] * m, b); i++) {
int dva = sq[i] + f[bl[a]];
if (dva < c) ans = max(dva, ans);
}
if (bl[a] != bl[b])
for (int i = (bl[b] - 1) * m + 1; i <= b; i++) {
int dva = sq[i] + f[bl[b]];
if (dva < c) ans = max(ans, dva);
}
for (int i = bl[a] + 1; i <= bl[b] - 1; i++) {
auto lt = s[i].lower_bound(c - f[i]);
if (lt == s[i].begin()) continue;
ans = max(ans, *--lt + f[i]);
}
return ans;
}
int main(int argc, char const *argv[]) {
scanf("%d", &n); m = sqrt(n);
for (int i = 1; i <= n; i++) scanf("%d", &sq[i]), bl[i] = (i - 1) / m + 1, s[bl[i]].insert(sq[i]);
for (int i = 1; i <= n; i++) {
scanf("%d%d%d%d", &opt, &a, &b, &c);
if (!opt) add(a, b, c);
else printf("%d\n", ask(a, b, c));
}
return 0;
}