Loj#6278. 数列分块入门 2

给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值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
分析:复习了一下分块.
   对于修改操作,在整块外的直接暴力修改,否则给每个块维护一个修改标记. 这样每个元素的最终值就是它本身 + 它所属块的修改标记.
   对于查询操作,整块外的暴力统计,整块内的需要给每一块排序,二分即可.
   几个易错点:
   1.不要直接排序原序列.
   2.注意序列的下标和块的下标不要弄混了.
   3.如果修改的区间在一个整块内,则直接暴力修改.
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll maxn = 50010;
ll n,block,pos[maxn],l[maxn],r[maxn],cnt,a[maxn],add[maxn];
vector <ll> b[maxn];

void Sort(int x)
{
    b[x].clear();
    for (int i = l[x]; i <= r[x]; i++)
        b[x].push_back(a[i]);
    sort(b[x].begin(),b[x].end());
}

void update(ll L,ll R,ll x)
{
    if (pos[L] == pos[R])
    {
        for (ll i = L; i <= R; i++)
            a[i] += x;
        Sort(pos[L]);
        return;
    }
    for (ll i = pos[L] + 1; i <= pos[R] - 1; i++)
        add[i] += x;
    for (ll i = L; i <= r[pos[L]]; i++)
        a[i] += x;
    for (ll i = l[pos[R]]; i <= R; i++)
        a[i] += x;
    Sort(pos[L]);
    Sort(pos[R]);
}

ll query(ll L,ll R,ll x)
{
    ll res = 0;
    if (pos[L] == pos[R])
    {
        for (ll i = L; i <= R; i++)
            if (a[i] + add[pos[i]] < x)
                res++;
        return res;
    }
    for (ll i = L; i <= r[pos[L]]; i++)
        if (a[i] + add[pos[i]] < x)
            res++;
    for (ll i = l[pos[R]]; i <= R; i++)
        if (a[i] + add[pos[i]]< x)
            res++;
    for (ll i = pos[L] + 1; i <= pos[R] - 1; i++)
    {
        int temp = x - add[i];
        res += lower_bound(b[i].begin(),b[i].end(),temp) - b[i].begin();
    }
    return res;
}

int main()
{
    freopen("test.txt","r",stdin);
    scanf("%lld",&n);
    block = sqrt(n);
    for (ll i = 1; i <= n; i++)
    {
        scanf("%lld",&a[i]);
        pos[i] = (i - 1) / block + 1;
        b[pos[i]].push_back(a[i]);
    }
    cnt = (n - 1) / block + 1;
    for (ll i = 1; i <= cnt; i++)
    {
        l[i] = r[i - 1] + 1;
        r[i] = min(i * block,n);
        sort(b[i].begin(),b[i].end());
    }
    for (ll i = 1; i <= n; i++)
    {
        ll opt,L,R,c;
        scanf("%lld%lld%lld%lld",&opt,&L,&R,&c);
        if (opt == 0)
            update(L,R,c);
        else
            printf("%lld\n",query(L,R,c*c));
    }

    return 0;
}

 

 
posted @ 2018-03-12 23:13  zbtrs  阅读(172)  评论(0编辑  收藏  举报