区间加法,询问区间内小于某个值 x 的元素个数的分块求条
  • 板块学术版
  • 楼主封禁用户
  • 当前回复1
  • 已保存回复1
  • 发布时间2024/3/12 12:59
  • 上次更新2024/3/12 17:25:34
查看原帖
区间加法,询问区间内小于某个值 x 的元素个数的分块求条
439609
封禁用户楼主2024/3/12 12:59
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=50005;
int n,a[N],opt,l,r,c,g,tag[N],id[N],d[N];
int sta(int a)
{
	return a*g-g+1;
}
int end(int a)
{
	return min(a*g,n);
}
void add(int l,int r,int c)
{
	if(id[l]==id[r])
	{
		for(int i=l;i<=r;i++) a[i]+=c;
		for(int i=sta(id[l]);id[i]==id[l];i++) d[i]=a[i];
		sort(d+sta(id[l]),d+end(id[l])+1);
		return;
	}
	for(int i=l;id[l]==id[i];i++) a[i]+=c;
	for(int i=r;id[r]==id[i];i--) a[i]+=c;
	for(int i=sta(id[l]);id[i]==id[l];i++) d[i]=a[i];
	for(int i=sta(id[r]);id[i]==id[r];i++) d[i]=a[i];
	sort(d+sta(id[l]),d+end(id[l])+1);
	sort(d+sta(id[r]),d+end(id[r])+1);
	for(int i=id[l]+1;i<id[r];i++) tag[i]+=c;
}
int query(int l,int r,int x)
{
	int ans=0;
	if(id[l]==id[r])
	{
		for(int i=l;i<=r;i++) if(a[i]+tag[id[l]]<x) ans++;
		return ans;
	}
	for(int i=l;id[l]==id[i];i++) if(a[i]+tag[id[l]]<x) ans++;
	for(int i=r;id[r]==id[i];i--) if(a[i]+tag[id[r]]<x) ans++;
	for(int i=id[l]+1;i<id[r];i++)
	{
		int L=sta(i),R=end(i),f=0,zx=1e18;
		while(L<=R)
		{
			int mid=(L+R)/2;
			if(d[mid]+tag[i]>=x)
			{
				f=1;
				zx=min(zx,mid);
				R=mid-1;
			}
			else L=mid+1;
		}
		if(f) ans+=zx-l;
	}
	return ans;
}
signed main()
{
	scanf("%lld",&n);
	g=sqrt(n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		d[i]=a[i];
		if(i%g==0) id[i]=i/g;
		else id[i]=i/g+1;
	}
	for(int i=1;i<=n;i+=g) sort(d+i,d+min(n+1,i+g));
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld%lld%lld",&opt,&l,&r,&c);
		if(l>r) swap(l,r);
		if(opt==0) add(l,r,c);
		else printf("%lld\n",query(l,r,c*c));
	}
	return 0;
}
2024/3/12 12:59
加载中...