分塊 二分 BZOJ 3343

2022-05-01 19:42:10 字數 2753 閱讀 8927

time limit: 10 sec  memory limit: 256 mb

submit: 1312  solved: 585

[submit][status][discuss]

教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給xmyz資訊組每個英雄看。於是n個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1、2、……、n。

每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間[l, r](1≤l≤r≤n)內的英雄的身高全部加上乙個整數w。(雖然l=r時並不符合區間的書寫規範,但我們可以認為是單獨增加第l(r)個英雄的身高)

cyz、光哥和zjq等人不信教主的邪,於是他們有時候會問wd閉區間 [l, r] 內有多少英雄身高大於等於c,以驗證教主的魔法是否真的有效。

wd巨懶,於是他把這個回答的任務交給了你。

第1行為兩個整數n、q。q為問題數與教主的施法數總和。

第2行有n個正整數,第i個數代表第i個英雄的身高。

第3到第q+2行每行有乙個操作:

(1)       若第乙個字母為「m」,則緊接著有三個數字l、r、w。表示對閉區間 [l, r] 內所有英雄的身高加上w。

(2)       若第乙個字母為「a」,則緊接著有三個數字l、r、c。詢問閉區間 [l, r] 內有多少英雄的身高大於等於c。

對每個「a」詢問輸出一行,僅含乙個整數,表示閉區間 [l, r] 內身高大於等於c的英雄數。

5 31 2 3 4 5

a 1 5 4

m 3 5 1

a 1 5 423

【輸入輸出樣例說明】

原先5個英雄身高為1、2、3、4、5,此時[1, 5]間有2個英雄的身高大於等於4。教主施法後變為1、2、4、5、6,此時[1, 5]間有3個英雄的身高大於等於4。

【資料範圍】

對30%的資料,n≤1000,q≤1000。

對100%的資料,n≤1000000,q≤3000,1≤w≤1000,1≤c≤1,000,000,000。

[submit][status][discuss]

思路:分塊以後,對於每個詢問區間[l,r],對於收尾兩個區間進行暴力尋找即可。對於中間的塊,我們提前進行排序然後進行二分尋找大於c-add[now_block_id]即可(因為每個塊是sqrt(n)個元素,所以總的複雜度應該是n*sqrt(n)*log(n))

//

看看會不會爆int!陣列會不會少了一維!

//取物問題一定要小心先手勝利的條件

#include using

namespace

std;

#pragma comment(linker,"/stack:102400000,102400000")

#define ll long long

#define all(a) a.begin(), a.end()

#define pb push_back

#define mk make_pair

#define fi first

#define se second

#define haha printf("haha\n")

const

int maxn = 1000000 + 5

;int

n, q;

intblock, num, belong[maxn], l[maxn], r[maxn];

intadd[maxn], a[maxn], d[maxn];

void

build_block()

r[num] =n;

for (int i = 1; i <= n; i++)

belong[i] = (i - 1) / block + 1

;

for (int i = 1; i <= num; i++)

}void modify(int l, int

r)void update(int ql, int qr, int

w)

for (int i = ql; i <= r[belong[ql]]; i++)

a[i] +=w;

modify(l[belong[ql]], r[belong[ql]]);

for (int i = l[belong[qr]]; i <= qr; i++)

a[i] +=w;

modify(l[belong[qr]], r[belong[qr]]);

for (int i = belong[ql] + 1; i < belong[qr]; i++)

add[i] +=w;

}int query(int ql, int qr, int

c)

for (int i = ql; i <= r[belong[ql]]; i++)

if (c - add[belong[ql]] <= a[i]) ans++;

for (int i = l[belong[qr]]; i <= qr; i++)

if (c - add[belong[qr]] <= a[i]) ans++;

for (int i = belong[ql] + 1; i < belong[qr]; i++)

return

ans;

}int

main()

build_block();

while (q--)

else

update(a, b, c);

}return0;

}

view code

bzoj3343 教主的魔法 分塊 二分)

原題位址 題意 由不超過1000的正整數組成的序列,標號1,2,3 n。教主的魔法 有m個詢問或操作,每次操作可以把閉區間 l,r 1 l r n 內的數全部加上乙個整數w,每次詢問閉區間 l,r 內有多少數大於等於c。資料範圍 n 1000000,q 3000,1 w 1000,1 c 1,000...

Bzoj 3343 教主的魔法 分塊 二分答案

3343 教主的魔法 time limit 10 sec memory limit 256 mb description 教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給xmyz資訊組每個英雄看。於是n個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1 2 n。每個人的身高一開始...

bzoj3343 教主的魔法 分塊

算是第一次寫分塊吧。這道題是最裸的分塊,每個塊上打上加標記,另外維護乙個塊內的排好序的陣列。對於修改操作,如果l,r在乙個塊內,暴力更改,之後重建。如果l,r不在乙個塊內,中間的塊處理標記,其餘部分暴力更改,之後重建。對於詢問操作,如果l,r在乙個塊內,暴力查詢 如果l,r不在乙個塊內,中間的塊裡二...