题目描述
给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数。
输入格式
第一行输入一个数字n。
第二行输入n个数字,第i个数字为ai,以空格隔开。
接下来输入n行询问,每行输入四个数字 opt、l、r、c,以空格隔开。
若opt=0 ,表示将位于 [l,r] 的之间的数字都加 。
若 opt=1,表示询问 [l,r] 中,小于 c^2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
数据范围与提示
对于100%的数据,
1≤n≤50000,
-2^31 ≤ others、ans ≤ 2^31-1
#include <iostream>
#include <string>
#include <cstring>
#include <ctime>
#include <fstream>
#include <cctype>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
// tip: belong[i]=(i-1)/sz+1; //sz指每一块的大小
int a[500010];
int belong[100010];
int sz;
int atag[100010];
int ans;
vector<int> G[500010]; //G[i]指第i块
int n;
void reset(int x) { //让第x块重新以从小到大排序
G[x].clear();
for (int i = (x - 1) * sz + 1; i <= min(x * sz, n); i++) G[x].push_back(a[i]); //把第i组的数重新压入G[i]
sort(G[x].begin(), G[x].end());
}
void add(int l, int r, int c) {
for (int i = l; i <= min(belong[l] * sz, r); i++) a[i] += c;
reset(belong[l]); //第l块的数据已经改变,重新设置数组顺序
if (belong[l] != belong[r]) {
for (int i = (belong[r] - 1) * sz + 1; i <= r; i++) a[i] += c;
reset(belong[r]); //同上
}
for (int i = belong[l] + 1; i <= belong[r] - 1; i++) {
atag[i] += c; //没有对原数据a[i]进行处理,因此不需要reset
}
}
int inquire(int l, int r, int c) { //查询
for (int i = l; i <= min(belong[l] * sz, r); i++) {
if (a[i] + atag[belong[i]] < c)
ans++;
}
if (belong[l] != belong[r]) {
for (int i = (belong[r] - 1) * sz + 1; i <= r; i++) {
if (a[i] + atag[belong[r]] < c)
ans++;
};
}
for (int i = belong[l] + 1; i <= belong[r] - 1; i++) {
ans += lower_bound(G[i].begin(), G[i].end(), c - atag[i]) - G[i].begin(); //注意要的是lower_bound而不是upper_bound,注意地址大小与个数之间的转换
}
return ans;
}
int main() {
while (cin >> n) {
int m = n;
sz = sqrt(n);
for (int i = 1; i <= n; i++) {
cin >> a[i];
belong[i] = (i - 1) / sz + 1;
G[belong[i]].push_back(a[i]);
}
memset(atag, 0, sizeof(atag));
for (int i = 1; i <= belong[n]; i++) sort(G[i].begin(), G[i].end()); //排序好序才能进行二分查找
while (m--) {
int opt, l, r, c;
cin >> opt >> l >> r >> c;
if (opt == 0) {
add(l, r, c);
} else if (opt == 1) {
ans = 0;
ans = inquire(l, r, c * c);
cout << ans << endl;
}
}
}
return 0;
}