關於分塊

題意:區間修改,然後查詢區間內小於x的元素的值的個數。

思路:依舊考慮分塊,對於已經在區間內的完整的塊,可以先對塊排序,然後直接二分,對於不完整的塊依舊暴力查詢,注意在每次修改後保證快內元素的有序性。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
vector<LL>v[1005];
char ch[20];
LL a[maxn],tag[maxn];
int blo,n,m;
int xx;
int l,r,bl[maxn];
void reset(int x) {
    v[x].clear();
    for(int i=(x-1)*blo+1;i<=min(x*blo,n);i++)
        v[x].push_back(a[i]);
    sort(v[x].begin(),v[x].end());
}
void change(int l,int r,int x) {
    for(int i=l;i<=min(r,blo*bl[l]);i++)
        a[i]+=x;
    reset(bl[l]);
    if(bl[l]!=bl[r]) {
        for(int i=(bl[r]-1)*blo+1;i<=r;i++)
            a[i]+=x;
        reset(bl[r]);
    }
    for(int i=bl[l]+1;i<=bl[r]-1;i++)
        tag[i]+=x;
}
int search(int l,int r,int x) {
    int ans=0;
    for(int i=l;i<=min(r,blo*bl[l]);i++) {
        if(a[i]+tag[bl[l]]<x) ans++;
    }
    if (bl[l]!=bl[r]){
     for (int i=(bl[r]-1)*blo+1;i<=r;i++)
      if (a[i]+tag[bl[r]]<x)  ans++;
    }
    for (int i=bl[l]+1;i<=bl[r]-1;i++){
      int t=x-tag[i];
      ans+=lower_bound(v[i].begin(),v[i].end(),t)-v[i].begin();
    }
   return ans;
}
int main() {
    scanf("%d%d",&n,&m);
    blo=sqrt(n);
    for(int i=1;i<=n;i++) {
        scanf("%lld",&a[i]);
        bl[i]=(i-1)/blo+1;
        v[bl[i]].push_back(a[i]);
    }
    for(int i=1;i<=bl[n];i++) {
        sort(v[i].begin(),v[i].end());
    }
    for (int i=1;i<=m;i++){
        scanf("%s",ch);
        scanf("%d%d%d",&l,&r,&xx);
        if (ch[0]=='C') change(l,r,xx);
        else printf("%d\n",search(l,r,xx));
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章