程式設計開發演算法 分塊問題解析

2022-09-23 16:00:13 字數 2894 閱讀 9274

分塊的基本思想是,將處理的一組數分成一些塊,對於每個l-r的操作,l和r兩端所在的不完整的塊單獨處理,其餘每個完整塊只需統計這個塊的資訊而不必遍歷這個塊內所有的元素,從而節約時間。 分塊大小通常可以使用根號n,但對於不同題目可以使用均值不等式找到更好的分塊大小。 hzwer的分塊教程 題目列表 簡易題解 notice:我的**元素個數都是0~n-1,塊的編號也是。這樣可以使用i/size找到i在第幾個塊,比較方便。 pro1 a[i]表示第i個數的值,block[i]表示第i個塊累加的值。 每次加法,對於不是乙個完整塊的部分,累加a[i]的值。 每次加法,對於是乙個完整塊的部分,累加block[i/size]的值。 每次詢問,輸出a[i]+block[i/size]。 **#include

#include

#include

#include

#include

using namespace std;

int a[51000],block[51000];

int main()

int a[51000],b[51000],block[51000];

int main()

int a[110000],b[110000],block[110000];

int main()

}return 0;

}pro4 a[i]表示第i個數的值,block[i]表示第i個塊累加的值,total[i]表示第i個塊的元素和。 每次加法,對於不是乙個完整塊的部分,累加a[i]的值,且為total[i/size]加上c。 每次加法,對於是乙個完整塊的部分,累加block[i/size]的值,且為total[i/size]加上c*size。 每次詢問,ans累加兩端不完整塊的a[i]+block[i/size],累加完整塊的total。 **:#include

#include

#include

#include

#include

#define ll long long

using namespace std;

ll a[110000],block[110000],total[110000];

int main()

l=l-now-1;

for(int i=num[nowblock]-1;i>=l;i--)

a[nowblock][i+1]=a[nowblock][i];

a[nowblock][l]=r;

num[nowblock]++;

n++;

//重構

if(inscnt==size)

printf("%d\n",a[nowblock][r-now-1]);

}

}return 0;

}pro7 我們使乙個元素的真正值為a[i]*blockmul[i/size]+blockadd[i/size]。 每次乘法,對於不完整塊的元素,更新其所在的塊的所有元素的a[i]值(使其變為真正的值),且清空所在塊blockmul和blockadd的值,然後再乘上c。 每次乘法,對於完整塊的元素,這些元素的真正值變為(a[i] * blockmul[i/size] + blockadd[i/size] )*c,也就是a[i]*blockmul[i/size]*c+blockadd[i/size]*c。 所以我們只要把這些塊的blockmul和blockadd都乘上c就好了。 每次加法,不完整部分也是更新元素a[i]值,然後清空blockmul和blockadd,然後加上c;完整塊直接加到該塊的blockadd就行了。 每次詢問,輸出該元素的真正值。 **:#include

#include

#include

#include

#include

#define mod (10007)

#define ll

using namespace std;

int size,a[110000],blockmul[110000],blockadd[110000];

void deal(int x)

int main()

{ for(int i=0;i<=100000;i++)blockmul[i]=1;

memset(blockadd,0,sizeof(blockadd));

int n;

scanf("%d",&n);

size=sqrt(n)+1;

for(int i=0;i

pro8

又是一題面向資料程式設計…

出點資料暴力一下,會發現幾次詢問後基本都是一大段一大段一樣的。

使用block[i/size]表示i所在的塊是否全部都是一樣的,如果是的話,這塊的所有元素的值都是a[i/size*size](也就是這個塊的第乙個元素的值)。

每次查詢時對於兩端的塊如果block=true,那麼就需要暴力把兩端塊內所有元素都換成塊內第乙個元素(也就是它真正的值)。因為當初我們改的時候只改了塊頭,其他值都是假的。

每次查詢時對於完整的塊,如果block=true那麼就看看c是否和塊頭一樣,是就加上size;不一樣的話就暴力統計。由於基本都是一樣的,只有少數幾個塊block=false,所以實際上還是很快的。

**:#include

#include

#include

#include

#include

#define mod (10007)

#define ll

using namespace std;

int a[110000];

bool block[110000];

int main()

{ memset(block,false,sizeof(block));

int n,size;

scanf("%d",&n);

size=sqrt(n)+1;

for(int i=0;i

pro9

正在研究。

程式設計開發序列求和問題解析

問題描述求1 2 3 n的值。輸入格式輸入包括乙個整數n。輸出格式輸出一行,包括乙個整數,表示1 2 3 n的值。樣例輸入4樣例輸出10樣例輸入100 說明 有一些試題會給出多組樣例輸入輸出以幫助你更好的做題。一般在提交之前所有這些樣例都需要測試通過才行,但這不代表這幾組樣例資料都正確了你的程式就是...

程式設計開發飛彈攔截問題解析

程式設計開發飛彈攔截問題解析。某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。輸...

程式設計開發親和數問題解析

程式設計開發親和數問題解析,古希臘數學家畢達哥拉斯在自然數研究中發現,220的所有真約數 即不是自身的約數 之和為 1 2 4 5 10 11 20 22 44 55 110 284。而284的所有真約數為1 2 4 71 142,加起來恰好為220。人們對這樣的數感到很驚奇,並稱之為親和數。一般地...