日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

LibreOJ 数列分块入门

發(fā)布時(shí)間:2024/10/12 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LibreOJ 数列分块入门 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目鏈接:https://loj.ac/problem/6277

?

題目描述

給出一個(gè)長(zhǎng)為?nnn?的數(shù)列,以及?nnn?個(gè)操作,操作涉及區(qū)間加法,單點(diǎn)查值。

輸入格式

第一行輸入一個(gè)數(shù)字?nnn。

第二行輸入?nnn?個(gè)數(shù)字,第?iii?個(gè)數(shù)字為?aia_ia?i??,以空格隔開(kāi)。

接下來(lái)輸入?nnn?行詢問(wèn),每行輸入四個(gè)數(shù)字?opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔開(kāi)。

若?opt=0\mathrm{opt} = 0opt=0,表示將位于?[l,r][l, r][l,r]?的之間的數(shù)字都加?ccc。

若?opt=1\mathrm{opt} = 1opt=1,表示詢問(wèn)?ara_ra?r???的值(lll?和?ccc?忽略)。

輸出格式

對(duì)于每次詢問(wèn),輸出一行一個(gè)數(shù)字表示答案。

樣例

樣例輸入

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

樣例輸出

2 5

數(shù)據(jù)范圍與提示

對(duì)于?100% 100\%100%?的數(shù)據(jù),1≤n≤50000,?231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1n50000,?2?31??others、ans≤231?1 \mathrm{ans} \leq 2^{31}-1ans2?31???1。

?

代碼如下:

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 5e4+10; 18 19 int block; 20 int a[MAXN], lazy[MAXN]; 21 void add(int pos, int c) 22 { 23 int B = pos/block; 24 for(int i = 0; i<B; i++) lazy[i] += c; 25 for(int i = B*block; i<=pos; i++) a[i] += c; 26 } 27 28 int main() 29 { 30 int n; 31 while(scanf("%d", &n)!=EOF) 32 { 33 block = sqrt(n); 34 for(int i = 0; i<n; i++) 35 scanf("%d", &a[i]); 36 int opt, l, r, c; 37 memset(lazy, 0, sizeof(lazy)); 38 for(int i = 0; i<n; i++) 39 { 40 scanf("%d%d%d%d",&opt,&l,&r,&c); 41 l--; r--; 42 if(opt==0) 43 { 44 add(r,c); 45 if(l!=0) add(l-1,-c); 46 } 47 else 48 printf("%d\n", a[r]+lazy[r/block]); 49 } 50 } 51 } View Code

?

?

?

題目描述

給出一個(gè)長(zhǎng)為?nnn?的數(shù)列,以及?nnn?個(gè)操作,操作涉及區(qū)間加法,詢問(wèn)區(qū)間內(nèi)小于某個(gè)值?xxx?的元素個(gè)數(shù)。

輸入格式

第一行輸入一個(gè)數(shù)字?nnn。

第二行輸入?nnn?個(gè)數(shù)字,第 i 個(gè)數(shù)字為?aia_ia?i??,以空格隔開(kāi)。

接下來(lái)輸入?nnn?行詢問(wèn),每行輸入四個(gè)數(shù)字?opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔開(kāi)。

若?opt=0\mathrm{opt} = 0opt=0,表示將位于?[l,r][l, r][l,r]?的之間的數(shù)字都加?ccc。

若?opt=1\mathrm{opt} = 1opt=1,表示詢問(wèn)?[l,r][l, r][l,r]?中,小于?c2c^2c?2???的數(shù)字的個(gè)數(shù)。

輸出格式

對(duì)于每次詢問(wèn),輸出一行一個(gè)數(shù)字表示答案。

樣例

樣例輸入

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

樣例輸出

3 0 2

數(shù)據(jù)范圍與提示

對(duì)于?100% 100\%100%?的數(shù)據(jù),1≤n≤50000,?231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1n50000,?2?31??others、ans≤231?1 \mathrm{ans} \leq 2^{31}-1ans2?31???1。

?

代碼如下:

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 1e5+10; 18 19 int n, block; 20 int a[MAXN], tmp[MAXN], lazy[MAXN]; 21 vector<int> v[MAXN]; 22 void add(int pos, int c) 23 { 24 int B = pos/block; 25 for(int i = 0; i<B; i++) lazy[i] += c; 26 for(int i = B*block; i<=pos; i++) a[i] += c; 27 for(int i = B*block; i<min(n,B*block+block); i++) tmp[i] = a[i]; 28 sort(tmp+B*block,tmp+min(n,B*block+block)); 29 } 30 31 int query(int pos, int c) 32 { 33 int ret = 0; 34 int B = pos/block; 35 for(int i = 0; i<B; i++) 36 ret += lower_bound(tmp+i*block, tmp+i*block+block, c*c-lazy[i]) - (tmp+i*block); 37 38 for(int i = B*block; i<=pos; i++) 39 if(a[i]+lazy[B]<c*c) ret++; 40 /* 41 錯(cuò)誤: 42 ret += lower_bound(tmp+B*block, tmp+pos+1, c*c-lazy[B]) - (tmp+B*block); 43 */ 44 return ret; 45 } 46 47 int main() 48 { 49 while(scanf("%d", &n)!=EOF) 50 { 51 block = sqrt(n); 52 for(int i = 0; i<n; i++) 53 scanf("%d", &a[i]), tmp[i] = a[i]; 54 55 for(int i = 0; i<block; i++) 56 sort(tmp+i*block, tmp+i*block+block); 57 sort(tmp+block*block, tmp+n); 58 59 int opt, l, r, c; 60 memset(lazy, 0, sizeof(lazy)); 61 for(int i = 0; i<n; i++) 62 { 63 scanf("%d%d%d%d", &opt,&l,&r,&c); 64 l--; r--; 65 if(opt==0) 66 { 67 add(r,c); 68 if(l) add(l-1, -c); 69 } 70 else 71 { 72 int ans = query(r, c); 73 if(l) ans -= query(l-1, c); 74 printf("%d\n", ans); 75 } 76 } 77 } 78 } View Code

?

?

題目描述

給出一個(gè)長(zhǎng)為?nnn?的數(shù)列,以及?nnn?個(gè)操作,操作涉及區(qū)間加法,詢問(wèn)區(qū)間內(nèi)小于某個(gè)值?xxx?的前驅(qū)(比其小的最大元素)。

輸入格式

第一行輸入一個(gè)數(shù)字?nnn。

第二行輸入?nnn?個(gè)數(shù)字,第 i 個(gè)數(shù)字為?aia_ia?i??,以空格隔開(kāi)。

接下來(lái)輸入?nnn?行詢問(wèn),每行輸入四個(gè)數(shù)字?opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔開(kāi)。

若?opt=0\mathrm{opt} = 0opt=0,表示將位于?[l,r][l, r][l,r]?的之間的數(shù)字都加?ccc。

若?opt=1\mathrm{opt} = 1opt=1,表示詢問(wèn)?[l,r][l, r][l,r]?中?ccc?的前驅(qū)的值(不存在則輸出??1-1?1)。

輸出格式

對(duì)于每次詢問(wèn),輸出一行一個(gè)數(shù)字表示答案。

樣例

樣例輸入

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

樣例輸出

3 -1

數(shù)據(jù)范圍與提示

對(duì)于?100% 100\%100%?的數(shù)據(jù),1≤n≤100000,?231≤others 1 \leq n \leq 100000, -2^{31} \leq \mathrm{others}1n100000,?2?31??others、ans≤231?1 \mathrm{ans} \leq 2^{31}-1ans2?31???1。

?

代碼如下:

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 1e5+10; 18 19 int n, block; 20 int a[MAXN], tmp[MAXN], lazy[MAXN]; 21 vector<int> v[MAXN]; 22 23 void reset(int B) 24 { 25 for(int i = B*block; i<min(n,B*block+block); i++) tmp[i] = a[i]; 26 sort(tmp+B*block,tmp+min(n,B*block+block)); 27 } 28 29 void add(int l, int r, int c) 30 { 31 int lB = l/block, rB = r/block; 32 for(int i = l; i<=min(r,lB*block+block-1); i++) a[i] += c; 33 reset(lB); 34 35 for(int i = lB+1; i<=rB-1; i++) lazy[i] += c; 36 if(lB!=rB) 37 { 38 for(int i = rB*block; i<=r; i++) a[i] += c; 39 reset(rB); 40 } 41 } 42 43 int query(int l, int r, int c) 44 { 45 int ret = -1; 46 int lB = l/block, rB = r/block; 47 for(int i = l; i<=min(r,lB*block+block-1); i++) 48 if(a[i]+lazy[lB]<c) ret = max(ret, a[i]+lazy[lB]); 49 for(int i = lB+1; i<=rB-1; i++) 50 { 51 int cnt = lower_bound(tmp+i*block, tmp+i*block+block, c-lazy[i]) - (tmp+i*block); 52 if(cnt) ret = max(ret, tmp[i*block+cnt-1]+lazy[i]); 53 } 54 if(lB!=rB) 55 { 56 for(int i = rB*block; i<=r; i++) 57 if(a[i]+lazy[rB]<c) ret = max(ret, a[i]+lazy[rB]); 58 } 59 return ret; 60 } 61 62 int main() 63 { 64 while(scanf("%d", &n)!=EOF) 65 { 66 block = sqrt(n); 67 for(int i = 0; i<n; i++) 68 scanf("%d", &a[i]), tmp[i] = a[i]; 69 70 for(int i = 0; i<block; i++) 71 sort(tmp+i*block, tmp+i*block+block); 72 sort(tmp+block*block, tmp+n); 73 74 int opt, l, r, c; 75 memset(lazy, 0, sizeof(lazy)); 76 for(int i = 0; i<n; i++) 77 { 78 scanf("%d%d%d%d", &opt,&l,&r,&c); 79 l--; r--; 80 if(opt==0) add(l,r,c); 81 else printf("%d\n", query(l,r, c)); 82 } 83 } 84 } View Code

?

?

?

題目描述

給出一個(gè)長(zhǎng)為?nnn?的數(shù)列,以及?nnn?個(gè)操作,操作涉及區(qū)間開(kāi)方,區(qū)間求和。

輸入格式

第一行輸入一個(gè)數(shù)字?nnn。

第二行輸入?nnn?個(gè)數(shù)字,第 i 個(gè)數(shù)字為?aia_ia?i??,以空格隔開(kāi)。

接下來(lái)輸入?nnn?行詢問(wèn),每行輸入四個(gè)數(shù)字?opt\mathrm{opt}opt、lll、rrr、ccc,以空格隔開(kāi)。

若?opt=0\mathrm{opt} = 0opt=0,表示將位于?[l,r][l, r][l,r]?的之間的數(shù)字都開(kāi)方。

若?opt=1\mathrm{opt} = 1opt=1,表示詢問(wèn)位于?[l,r][l, r][l,r]?的所有數(shù)字的和。

輸出格式

對(duì)于每次詢問(wèn),輸出一行一個(gè)數(shù)字表示答案。

樣例

樣例輸入

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

樣例輸出

6 2

數(shù)據(jù)范圍與提示

對(duì)于?100% 100\%100%?的數(shù)據(jù),1≤n≤50000,?231≤others 1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1n50000,?2?31??others、ans≤231?1 \mathrm{ans} \leq 2^{31}-1ans2?31???1。

?

代碼如下:

1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <vector> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-8; 15 const int INF = 2e9; 16 const LL LNF = 2e18; 17 const int MAXN = 1e5+10; 18 19 int n, block; 20 int a[MAXN], tmp[MAXN], cnt[MAXN], vis[MAXN], sum[MAXN]; 21 void add(int l, int r) 22 { 23 int lB = l/block, rB = r/block; 24 for(int i = l; i<=min(r,lB*block+block-1); i++) 25 { 26 int val = sqrt(a[i]); 27 sum[lB] += val - a[i]; 28 a[i] = val; 29 if((val==1||val==0)&&!vis[i]) 30 vis[i] = 1, cnt[lB]--; 31 } 32 33 for(int i = lB+1; i<=rB-1; i++) 34 if(cnt[i]) 35 { 36 for(int j = i*block; j<i*block+block; j++) 37 { 38 int val = sqrt(a[j]); 39 sum[i] += val-a[j]; 40 a[j] = val; 41 if((val==1||val==0)&&!vis[j]) 42 vis[j] = 1, cnt[i]--; 43 } 44 } 45 if(lB!=rB) 46 { 47 for(int i = rB*block; i<=r; i++) 48 { 49 int val = sqrt(a[i]); 50 sum[rB] += val - a[i]; 51 a[i] = val; 52 if((val==1||val==0)&&!vis[i]) 53 vis[i] = 1, cnt[rB]--; 54 } 55 } 56 } 57 58 int query(int l, int r) 59 { 60 int ret = 0; 61 int lB = l/block, rB = r/block; 62 for(int i = l; i<=min(r,lB*block+block-1); i++) 63 ret += a[i]; 64 for(int i = lB+1; i<=rB-1; i++) 65 ret += sum[i]; 66 if(lB!=rB) 67 { 68 for(int i = rB*block; i<=r; i++) 69 ret += a[i]; 70 } 71 return ret; 72 } 73 74 int main() 75 { 76 while(scanf("%d", &n)!=EOF) 77 { 78 block = sqrt(n); 79 memset(cnt, 0, sizeof(cnt)); 80 memset(vis, 0, sizeof(vis)); 81 memset(sum, 0, sizeof(sum)); 82 for(int i = 0; i<n; i++) 83 scanf("%d", &a[i]), cnt[i/block]++, sum[i/block] += a[i]; 84 85 int opt, l, r, c; 86 for(int i = 0; i<n; i++) 87 { 88 scanf("%d%d%d%d", &opt,&l,&r,&c); 89 l--; r--; 90 if(opt==0) add(l,r); 91 else printf("%d\n", query(l,r)); 92 } 93 } 94 } View Code

?

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/DOLFAMINGO/p/8681099.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的LibreOJ 数列分块入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。