社区讨论

救救孩子吧 必关

P13977数列分块入门 2参与者 1已保存回复 0

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
0 条
当前快照
1 份
快照标识符
@mkmbdsjn
此快照首次捕获于
2026/01/20 16:10
4 周前
此快照最后确认于
2026/01/20 16:19
4 周前
查看原帖
分块+二分,WA on #1#8#11#19 , 其余 TLE 。
求调,悬关。
代码CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,len,a[200010],b[200010],bl[200010],lazy[1010];
inline int left(int k){return (k-1)*len+1;}
inline int right(int k){return min(k*len,n);}
inline void rebuild(int k)
{
	int l=left(k),r=right(k);
	if(l>r)return;
	for(int i=l;i<=r;i++)a[i]=b[i];
	sort(a+l,a+r+1);
}
inline void push_down(int k)
{
	int l=left(k),r=right(k);
	if(l>r)return;
	for(int i=l;i<=r;i++)
	{
		a[i]+=lazy[k];
		b[i]+=lazy[k];
	}
	lazy[k]=0;
}
signed main()
{
	int m,op,l,r,c,x,L,R,mid,ans;
	scanf("%lld",&n);
	m=n,len=sqrt(n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		b[i]=a[i];
		bl[i]=(i-1)/len+1;
	}
	for(int i=1;i<=n/len+1;i++)rebuild(i);
	while(m--)
	{
		scanf("%lld%lld%lld%lld",&op,&l,&r,&c);
		if(!op)
		{
			push_down(bl[l]);
			push_down(bl[r]);
			if(bl[l]==bl[r])
			{
				for(int i=l;i<=r;i++)b[i]+=c;
				rebuild(bl[l]);
			}
			else
			{
				for(int i=l;i<=right(bl[l]);i++)
				{
					b[i]+=c;
					rebuild(bl[l]);
				}
				for(int i=left(bl[r]);i<=r;i++)
				{
					b[i]+=c;
					rebuild(bl[r]);
				}
				for(int i=bl[l]+1;i<bl[r];i++)lazy[i]+=c;
			}
		}
		else
		{
			x=c*c;
			push_down(bl[l]);
			push_down(bl[r]);
			ans=0;
			for(int i=l;i<=right(bl[l]);i++)if(a[i]<x)ans++;
			for(int i=left(bl[r]);i<=r;i++)if(a[i]<x)ans++;
			for(int i=bl[l]+1;i<bl[r];i++)
			{
				L=left(i),R=right(i);
				while(L<=R)
				{
					mid=(L+R)/2;
					if(a[mid]<x-lazy[i])L=mid+1;
					else R=mid-1;
				}
				ans+=(L-left(i));
			}
			printf("%lld\n",ans);
		}
	}
	return 0;
}
我真没招了。

回复

0 条回复,欢迎继续交流。

正在加载回复...