题目描述
给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的元素个数。
输入格式
第一行输入一个数字 nnn。
第二行输入 nnn 个数字,第 iii 个数字为 aia_iai,以空格隔开。
接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔开。
若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字都加 ccc。
若 opt=1\mathrm{opt} = 1opt=1,表示询问 [l,r][l, r][l,r] 中,小于 c2c^2c2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
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% 100\% 100% 的数据,1≤n≤50000,−231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1 ans≤231−1。
这道水题调了我接近50分钟,不开心。
一开始以为没开longlong,实际上没有仔细读题,我还以为是求区间中小于等于$c^2$的个数呢...然后就因为没仔细读题贡献了接近一页的wa。
这题分块做,对于每个块,在块内进行排序,为了方便用vector存储就行了,然后修改的时候,整块直接打标记,零散的块整个暴力重构,查询整块在vector内二分,零散的暴力。
反正题的数据范围也不强,这个水题随便写写就能过。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <vector> #include <queue> using namespace std; #define reg register #define int long long inline int read() { int res = 0;char ch=getchar();bool fu=0; while(!isdigit(ch))fu|=(ch=='-'),ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return fu?-res:res; } int Bl = 500; #define N 50005 int n; int a[N]; int belong[N]; int L[5005], R[5005], tag[5005]; vector <int> ve[5005]; signed main() { n = read(); for (reg int i = 1 ; i <= n ; i ++) a[i] = read(); Bl = sqrt(n); for (reg int i = 1 ; i <= n ; i ++) { belong[i] = (i - 1) / Bl + 1; if (!L[belong[i]]) L[belong[i]] = i, R[belong[i]-1] = i - 1; } R[belong[n]] = n; for (reg int i = 1 ; i <= n ; i ++) ve[belong[i]].push_back(a[i]); for (reg int i = 1 ; i <= belong[n] ; i ++) sort(ve[i].begin(), ve[i].end()); int Q = n; while(Q--) { int opt = read(), l = read(), r = read(), c = read(); if (opt == 0) { if (belong[l] == belong[r]) { ve[belong[l]].clear(); for (reg int i = l ; i <= r ; i ++) a[i] += c; for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++) ve[belong[i]].push_back(a[i]); sort(ve[belong[l]].begin(), ve[belong[l]].end()); } else if (belong[l] + 1 == belong[r]) { ve[belong[l]].clear(); for (reg int i = l ; i <= R[belong[l]] ; i ++) a[i] += c; for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++) ve[belong[i]].push_back(a[i]); sort(ve[belong[l]].begin(), ve[belong[l]].end()); ve[belong[r]].clear(); for (reg int i = L[belong[r]] ; i <= r ; i ++) a[i] += c; for (reg int i = L[belong[r]] ; i <= R[belong[r]] ; i ++) ve[belong[i]].push_back(a[i]); sort(ve[belong[r]].begin(), ve[belong[r]].end()); } else { for (reg int i = belong[l] + 1 ; i <= belong[r] - 1 ; i ++) tag[i] += c; ve[belong[l]].clear(); for (reg int i = l ; i <= R[belong[l]] ; i ++) a[i] += c; for (reg int i = L[belong[l]] ; i <= R[belong[l]] ; i ++) ve[belong[i]].push_back(a[i]); sort(ve[belong[l]].begin(), ve[belong[l]].end()); ve[belong[r]].clear(); for (reg int i = L[belong[r]] ; i <= r ; i ++) a[i] += c; for (reg int i = L[belong[r]] ; i <= R[belong[r]] ; i ++) ve[belong[i]].push_back(a[i]); sort(ve[belong[r]].begin(), ve[belong[r]].end()); } } else { c *= c; int ans = 0; if (belong[l] == belong[r]) { for (reg int i = l ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++; printf("%lld\n", ans); } else if (belong[l] + 1 == belong[r]) { for (reg int i = l ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++; printf("%lld\n", ans); } else { for (reg int i = l ; i <= R[belong[l]] ; i ++) if (a[i] + tag[belong[i]] < c) ans++; for (reg int i = L[belong[r]] ; i <= r ; i ++) if (a[i] + tag[belong[i]] < c) ans++; for (reg int i = belong[l] + 1 ; i <= belong[r] - 1 ; i ++) ans += lower_bound(ve[i].begin(), ve[i].end(), c - tag[i]) - ve[i].begin(); printf("%lld\n", ans); } } } return 0; }