求助分块,开O2 80,剩下TLE

P2801 教主的魔法

崔化博 @ 2022-02-19 11:22:29

RT


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define N 1000005
using namespace std;
int block[N],a[N],blk[N],n,siz,m,x,y,k;
char c;
vector<int> blck[N];
void ppp(int x){
    blck[x].clear();
    for(register int i=(x-1)*siz+1;i<=min(n,x*siz);++i)
        blck[x].push_back(a[i]);
    sort(blck[x].begin(),blck[x].end());
}
void add(int l,int r,int k){
    for(register int i=l;i<=min(r,blk[l]*siz);++i)
        a[i]+=k;
    ppp(blk[l]);
    if(blk[l]!=blk[r]){
        for(register int i=(blk[r]-1)*siz+1;i<=r;++i)
            a[i]+=k;
        ppp(blk[r]);
    }
    for(register int i=blk[l]+1;i<=blk[r]-1;++i)
        block[i]+=k;
}
int query(int l,int r,int k){
    int ans=0;
    for(register int i=l;i<=min(r,blk[l]*siz);++i)
        if(a[i]>=k-block[blk[i]])
            ++ans;
    if(blk[l]!=blk[r])
        for(register int i=(blk[r]-1)*siz+1;i<=r;++i)
            if(a[i]>=k-block[blk[i]])
                ++ans;
    for(register int i=blk[l]+1;i<=blk[r]-1;++i){
        register int pp=k-block[i];
        ans+=blck[i].end()-lower_bound(blck[i].begin(),blck[i].end(),pp);
//      cout<<ans<<endl;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
    cin>>n>>m;
    siz=sqrt(n/log(n));
    for(register int i=1;i<=n;++i){
        cin>>a[i];
        blk[i]=(i-1)/siz+1;
        blck[blk[i]].push_back(a[i]);
        sort(blck[blk[i]].begin(),blck[blk[i]].end());
    }
    for(register int i=1;i<=m;++i){
        cin>>c>>x>>y>>k;
        if(c=='M'){
            add(x,y,k);
        }
        else{
            cout<<query(x,y,k)<<"\n";
        }
    }
    return 0;
}

|