[LOJ6278]数列分块入门 2

题目描述

给出一个长为 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}1n50000,231​​others、ans≤231−1 \mathrm{ans} \leq 2^{31}-1 ans231​​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;
}

猜你喜欢

转载自www.cnblogs.com/BriMon/p/9859307.html