• LOJ #6278. 数列分块入门 2-分块(区间加法、查询区间内小于某个值x的元素个数)


    内存限制:256 MiB时间限制:500 ms标准输入输出
    题目类型:传统评测方式:文本比较
    上传者: hzwer

    题目描述

    给出一个长为 nn 的数列,以及 nn 个操作,操作涉及区间加法,询问区间内小于某个值 xx 的元素个数。

    输入格式

    第一行输入一个数字 nn。

    第二行输入 nn 个数字,第 ii 个数字为 a_iai,以空格隔开。

    接下来输入 nn 行询问,每行输入四个数字 mathrm{opt}opt、ll、rr、cc,以空格隔开。

    若 mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都加 cc。

    若 mathrm{opt} = 1opt=1,表示询问 [l, r][l,r] 中,小于 c^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% 的数据,1 leq n leq 50000, -2^{31} leq mathrm{others}1n50000,231others、mathrm{ans} leq 2^{31}-1ans2311。

    代码:

    //#6278. 数列分块入门 2-区间加法,查询区间内小于某个值x的元素个数
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=5e4+10;
    
    int n,m;
    ll a[maxn],b[maxn],pos[maxn],tag[maxn];
    
    void rechange(int x)
    {
        for(int i=(x-1)*m+1;i<=min(x*m,n);i++){
                b[i]=a[i];
        }
        sort(b+(x-1)*m+1,b+min(x*m,n)+1);
    }
    
    void update(int l,int r,ll c)
    {
        if(pos[l]==pos[r]){
            for(int i=l;i<=r;i++)
                a[i]+=c;
            rechange(pos[l]);
        }
        else{
            for(int i=l;i<=pos[l]*m;i++)
                a[i]+=c;
            rechange(pos[l]);
            for(int i=pos[l]+1;i<=pos[r]-1;i++)
                tag[i]+=c;
            for(int i=(pos[r]-1)*m+1;i<=r;i++)
                a[i]+=c;
            rechange(pos[r]);
        }
    }
    
    int getnum(int l,int r,int c)
    {
        int num=0;
        if(pos[l]==pos[r]){
            for(int i=l;i<=r;i++){
                if(a[i]+tag[pos[l]]<c) num++;
            }
        }
        else{
            for(int i=l;i<=pos[l]*m;i++){
                if(a[i]+tag[pos[l]]<c) num++;
            }
            for(int i=pos[l]+1;i<=pos[r]-1;i++){
                int cnt=c-tag[i];
                num+=lower_bound(b+(i-1)*m+1,b+i*m+1,cnt)-b-(i-1)*m-1;//少减一wa
            }
            for(int i=(pos[r]-1)*m+1;i<=r;i++){
                if(a[i]+tag[pos[r]]<c) num++;
            }
        }
        return num;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        m=sqrt(n);
        for(int i=1;i<=n;i++)
            pos[i]=(i-1)/m+1;
        for(int i=1;i<=m+1;i++){
            sort(b+(i-1)*m+1,b+min(i*m,n)+1);
        }
        for(int i=1;i<=n;i++){
            int op,l,r;
            ll c;
            scanf("%d%d%d%lld",&op,&l,&r,&c);
            if(op==0){
                update(l,r,c);
            }
            else{
                printf("%d
    ",getnum(l,r,c*c));
            }
        }
        return 0;
    }
    
    
    /*
    5
    1 3 7 2 5
    0 1 3 1
    1 1 3 2
    1 1 4 1
    1 2 3 2
    1 3 5 4
    
    1
    0
    0
    3
    */
    
    /*
    10
    1 3 4 2 5 7 11 3 5 1
    0 1 5 1
    1 1 7 2
    0 3 9 1
    1 4 8 2
    1 1 10 2
    1 3 5 3
    1 5 10 3
    1 6 10 2
    1 2 7 2
    1 2 7 3
    
    
    2
    0
    2
    3
    5
    1
    0
    5
    */
  • 相关阅读:
    F. Maximum White Subtree 树形dp*换根
    D
    E
    两圆相交板子
    lucass定理
    高精度求组合数
    康托展开与康托逆展开
    FFT变换
    Codeforces Round #625 Div. 1 Problem C
    E.Multiply Pollard_rho质因数分解
  • 原文地址:https://www.cnblogs.com/ZERO-/p/10525630.html
Copyright © 2020-2023  润新知