求助分块,开O2 80,剩下TLE
查看原帖
求助分块,开O2 80,剩下TLE
304524
崔化博楼主2022/2/19 11:22

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;
}
2022/2/19 11:22
加载中...