ブロックの基本(シンプルで理解しやすい)

ブロック

ブロッキングは、主に間隔の問題のために、エレガントな暴力であると考えられています。

ブロッキングとは、セグメントを多くのブロックに分割することを意味します。

通常、ブロックのサイズを表すためにx = sqrt(n)を使用します

num = ceil(n ×\回× 1.0 / x)ブロック数を示します

チャンク化の主な要件は3つの配列です。

pos [i]は、i番目の番号が配置されているブロックを示します。

l [i]は、i番目のブロックの左端を表します

r [i]は、i番目のブロックの右端点を表します

たとえば、次の質問

i番目のブロックに追加した番号を表す別のans [i]配列を作成する必要があります

しかし、これは質問を生み出します。追加された間隔に含まれるi番目のブロックが不完全な場合、ans [i]にcを追加できますか。

答えはノーです。

不完全なブロックの場合、配列、つまり元の配列にcを追加して、それらを激しく解決する必要があります。

完全なブロックの場合、ans配列にcを追加するだけで済みます。

したがって、最終的な結果は、i番目の数値のサイズがa [i] + ans [pos [i]]になることです。

タイトル説明

長さnおよびnの操作のシーケンスが与えられた場合、操作には間隔の追加とシングルポイントルックアップが含まれます。

入力フォーマット

最初の行に番号を入力します。2行目にn個の数字を入力すると、i番目の数字はa [i]で、スペースで区切られます。

次に、クエリをn行入力し、スペースで区切って各行に4桁のopt、l、r、cを入力します。

opt = 0の場合、[l、r]の間のすべての数値にcを追加することを意味します。

場合OPT = 1、それは[R]の値を求める手段と

出力フォーマット

クエリごとに、回答を示す番号を1行に出力します。

サンプル

サンプル入力

4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

サンプル出力

2
5
#include<bits/stdc++.h>
using namespace std;
int l[2005],r[2005] ,pos[50005],a[50005],ans[50005];
void add(int ll,int rr,int v)
{
	int posl=pos[ll];
	int posr=pos[rr];
	if(posr-posl<=1)/*这个表示要加的区间在一个块内,即直接在原数组a上加*/
	{
		for(int i=ll;i<=rr;i++)
		{
			a[i]=a[i]+v;
		}
		
	}
	else
	{
		for(int i=ll;i<=r[posl];i++)/*前面的不完整的块*/
		a[i]=a[i]+v;
		for(int i=pos[ll]+1;i<pos[rr];i++)/*完整的块*/
		ans[i]+=v;
		for(int i=l[posr];i<=rr;i++)/*后面不完整的块*/
		a[i]=a[i]+v;
	}
	
}
void shuchu(int rr)
{
	if(ans[pos[rr]])
	printf("%d\n",a[rr]+ans[pos[rr]]);
	else
	printf("%d\n",a[rr]);
}
int main()
{
	int n;
	int opt ,ll,rr,cc;
	cin>>n;
	int x=sqrt(n);
	int num=ceil(n*1.0/x);
	for(int i=1;i<=num;i++)/*预处理l和r 数组*/
	{
		l[i]=(i-1)*x+1;
		r[i]=i*x;
	}
	r[num]=n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		pos[i]=(i-1)/x+1;	/*处理pos数组*/
	}
	for(int i=1;i<=n;i++)
	{
		cin>>opt>>ll>>rr>>cc;
		if(opt==0)
		{
			add(ll,rr,cc);
		}
		else
		{
			shuchu(rr);
		}
		
	}
	return 0;
}

おすすめ

転載: blog.csdn.net/hhuhgfhggy/article/details/108978595