洛谷 P2801
题目链接: P2801 教主的魔法
题目大意
一个序列 \(n\) 有区间加和及查询区间有多少个元素大于 \(c\)
solution
我们对每个块进行操作,对于每个块排序
修改操作:对于整块我们记录一下加的之即可,顺序没有改变,然后对于不足整块,我们直接加和然后排序
查询操作:对于整块我们 lower_bound 查找即可, 用块长减去查找的位置即可, 然后对于不足整块, 我们直接枚举查找
Code
/**
* Author: Alieme
* Data: 2020.9.8
* Problem: Lougu P2801
* Time: O()
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define int long long
#define rr register
#define inf 1e9
#define MAXN 1000010
using namespace std;
inline int read() {
int s = 0, f = 0;
char ch = getchar();
while (!isdigit(ch)) f |= ch == '-', ch = getchar();
while (isdigit(ch)) s = s * 10 + (ch ^ 48), ch = getchar();
return f ? -s : s;
}
void print(int x) {
if (x < 0) putchar('-'), x = -x;
if (x > 9) print(x / 10);
putchar(x % 10 + 48);
}
int n, len, m;
int a[MAXN], b[MAXN], id[MAXN], v[MAXN];
inline void update(int x) {
int l = (x - 1) * len + 1, r = min(x * len, n);
for (rr int i = l; i <= r; i++) b[i] = a[i];
sort(b + l, b + r + 1);
}
inline void add(int l, int r, int x) {
int start = id[l], end = id[r];
if (start == end) {
for (rr int i = l; i <= r; i++) a[i] += x;
update(id[l]);
return ;
}
for (rr int i = l; id[i] == start; i++) a[i] += x; update(start);
for (rr int i = start + 1; i < end; i++) v[i] += x;
for (rr int i = r; id[i] == end; i--) a[i] += x; update(end);
}
inline int fin(int pid, int x) {
int l = (pid - 1) * len + 1, r = min(pid * len, n);
return lower_bound(b + l, b + r + 1, x - v[pid]) - (b + l);
}
inline int query(int l, int r, int x) {
int ans = 0, start = id[l], end = id[r];
if (start == end) {
for (rr int i = l; i <= r; i++) if (a[i] + v[start] >= x) ans++;
return ans;
}
for (rr int i = l; id[i] == start; i++) if (a[i] + v[id[i]] >= x) ans++;
for (rr int i = start + 1; i < end; i++) ans += len - fin(i, x);
for (rr int i = r; id[i] == end; i--) if (a[i] + v[id[i]] >= x) ans++;
return ans;
}
signed main() {
n = read();
m = read();
len = sqrt(n);
for (rr int i = 1; i <= n; i++) a[i] = read(), id[i] = (i - 1) / len + 1;
for (rr int i = len; i <= n; i += len) update(id[i]);
for (rr int i = 1; i <= m; i++) {
char opt;
cin >> opt;
int l = read(), r = read(), c = read();
if (opt == 'M') add(l, r, c);
if (opt == 'A') cout << query(l, r, c) << "\n";
}
}
时间会刺破青春表面的彩饰,会在美人的额上掘深沟浅槽;会吃掉稀世之珍!天生丽质,什么都逃不过他那横扫的镰刀。
博主写的那么好,就不打赏一下么(打赏在右边)