• 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
    ",query(L,R,c*c));
        }
    
        return 0;
    }
     
  • 相关阅读:
    Spring Boot 详细简介
    Linux 安装 MySQL 8 数据库(图文详细教程)
    有了这个日期工具类,让日期转化不再烦恼
    Linux常用实用命令
    Java分割中英文,并且中文不能分割一半?
    Spring MVC或Spring Boot配置默认访问页面不生效?
    js如何判断当前页面是否处于激活状态
    博客园 & 陌上花开HIMMR | 脱单倒计时!只能帮你到这了
    博客园 & 陌上花开HIMMR | 距2020年脱单,只剩34天!
    博客园 & 陌上花开HIMMR | 脱单倒计时!刚过完10.24的你,还想一个人过11.11吗?
  • 原文地址:https://www.cnblogs.com/zbtrs/p/8552705.html
Copyright © 2020-2023  润新知