【分块】#6278. 数列分块入门 2 (区间修改、查询权值c在区间中的排名)

题目传送门

在这里插入图片描述

在这里插入图片描述
题解By hzwer
在这里插入图片描述

#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef int ll;

const int N = 500007, M = 5000007, INF = 0x3f3f3f3f;

ll read()
{
    ll x = 0, f = 1;char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')f = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

vector<ll>vt[50007];
ll block;
ll n, m;
ll bi[N], add_tag[N];
ll v[N];

void reset(ll x)//第x个块
{
    vt[x].clear();
    for(int i = (x - 1) * block + 1; i <= min(x * block, n); ++ i)
        vt[x].push_back(v[i]);
    sort(vt[x].begin(), vt[x].end());
}

void modify(ll a, ll b, ll k)
{
    for(int i = a; i <= min(bi[a] * block, b); ++ i)
        v[i] += k;
    reset(bi[a]);
    if(bi[a] != bi[b]){
        for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i)
            v[i] += k;
        reset(bi[b]);
    }
    for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i)
        add_tag[i] += k;
}

ll query(ll a, ll b, ll c)//查询排名
{
    ll ans = 0;
    for(int i = a; i <= min(bi[a] * block, b); ++ i)
        if(v[i] + add_tag[bi[a]] < c)
            ans ++ ;
    if(bi[a] != bi[b]){
        for(int i = (bi[b] - 1) * block + 1; i <= b; ++ i)
            if(v[i] + add_tag[bi[b]] < c)
                ans ++ ;
    }
    for(int i = bi[a] + 1; i <= bi[b] - 1; ++ i){
        ll x = c - add_tag[i];
        ans += lower_bound(vt[i].begin(), vt[i].end(), x) - vt[i].begin();
        //得到的是大于等于c的第一个树的下标,从0开始所以不用-1
    }
    return ans;
}

int main()
{
    n = read();block = sqrt(n);
    for(int i = 1; i <= n; ++ i)
        v[i] = read();
    for(int i = 1; i <= n; ++ i){
        bi[i] = (i - 1) / block + 1;
        vt[bi[i]].push_back(v[i]);
    }

    for(int i = 1; i <= bi[n]; ++ i)
        sort(vt[i].begin(), vt[i].end());
//我TM以后再也不用 while(n -- )了!!!
    for(int i = 1; i <= n; ++ i){
        int op = read(), l = read(), r = read(), c = read();
        if(op == 0) {
            modify(l, r, c);
        }
        if(op == 1) {
            printf("%d\n", query(l, r, (ll)c * c));
        }
    }
    return 0;
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页