教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給xmyz資訊組每個英雄看。於是n個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1、2、……、n。每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間[l, r](1≤l≤r≤n)內的英雄的身高全部加上乙個整數w。(雖然l=r時並不符合區間的書寫規範,但我們可以認為是單獨增加第l(r)個英雄的身高)
cyz、光哥和zjq等人不信教主的邪,於是他們有時候會問wd閉區間 [l, r] 內有多少英雄身高大於等於c,以驗證教主的魔法是否真的有效。
wd巨懶,於是他把這個回答的任務交給了你。
分塊演算法是指把乙個序列分成sqrt(n)塊,每塊正好有sqrt(n)個元素
對於這道題,我們先將每個數按順序分到乙個塊中,維護每個塊內部的單調性
對於乙個m操作,我們把l,r中間的塊整塊作乙個加法的標記,對於兩頭的直接暴力標
整塊不超過sqrt(n)塊,兩頭的也不超過sqrt(n)個元素,所以時間複雜度還是o(sqrt(n))
對於a操作,對於暴力的部分很容易統計,對於整塊的由於我們之前維護好了單調性,直接二分查詢就可以了
但是這裡不要忽略了之前作的add標記
145program bzoj3343;
6const maxn=1000010;maxm=1010;7
varn,q,m,block,x,y,z,i:longint;
8 ch:char
;9 a,b,pos:array[-1
..maxn]of longint;
10 add:array[-1
..maxm]of longint;
1112
function min(a,b:longint):longint;
13begin
14if aelse
exit(b);
15end;
1617
procedure qsort(l,r:longint);
18var
i,j,mid:longint;
19begin
20 i:=l;j:=r;mid:=b[random(r-l+1)+l];
21repeat
22while (imid) do
inc(i);
23while (ldo
dec(j);
24if i<=j then
25begin
26 b[0]:=b[i];b[i]:=b[j];b[j]:=b[0
];27
inc(i);dec(j);
28end;
29 until i>j;
30if i31if l32end;
3334 procedure new
(p:longint);
35var
l,r,i:longint;
36begin
37 l:=(p-1)*block+1;r:=min(p*block,n);
38for i:=l to r do b[i]:=a[i];
39qsort(l,r);
40end;
4142
procedure update(x,y,z:longint);
43var
i:longint;
44begin
45if pos[x]=pos[y] then
46for i:=x to y do inc(a[i],z) else
47begin
48for i:=x to pos[x]*block do
inc(a[i],z);
49for i:=(pos[y]-1)*block+1 to y do
inc(a[i],z);
50end;
51for i:=pos[x]+1 to pos[y]-1
doinc(add[i],z);
52new(pos[x]);new
(pos[y]);
53end;
5455
function find(x,y:longint):longint;
56var
l,r,mid:longint;
57begin
58 find:=(x-1)*block;
59 l:=(x-1)*block+1;r:=x*block;
60while l<=r do
61begin
62 mid:=(l+r) >> 1;63
if b[mid]>=y then
64begin
65 find:=mid;l:=mid+1
;66 end else r:=mid-1;67
end;
68 dec(find,(x-1)*block);
69end;
7071
function query(x,y,z:longint):longint;
72var
tot,i:longint;
73begin
74 tot:=0;75
if pos[x]=pos[y] then
76 begin for i:=x to y do
if a[i]>=z then inc(tot);end else
77begin
78for i:=x to pos[x]*block do
if a[i]>=z then inc(tot);
79for i:=(pos[y]-1)*block+1 to y do
if a[i]>=z then inc(tot);
80end;
81for i:=pos[x]+1 to pos[y]-1
do inc(tot,find(i,z-add[i]));
82exit(tot);
83end;
8485
begin
86readln(n,q);
87 fillchar(add,sizeof(add),0
);88 block:=trunc(sqrt(n));
89for i:=1 to n do
90begin
91read(a[i]);
92 pos[i]:=(i-1) div block+1;//
pos[i]表示第i個數所在的塊
93end;
94readln;
95if n mod block=0 then m:=n div block else m:=n div block +1;96
for i:=1 to m do
new(i);
97for i:=1 to q do
98begin
99read(ch);
100if ch='m'
then
101begin
102readln(x,y,z);
103update(x,y,z);
104 end else
105begin
106readln(x,y,z);
107writeln(query(x,y,z));
108end;
109end;
110 end.
bzoj3343 教主的魔法 分塊
算是第一次寫分塊吧。這道題是最裸的分塊,每個塊上打上加標記,另外維護乙個塊內的排好序的陣列。對於修改操作,如果l,r在乙個塊內,暴力更改,之後重建。如果l,r不在乙個塊內,中間的塊處理標記,其餘部分暴力更改,之後重建。對於詢問操作,如果l,r在乙個塊內,暴力查詢 如果l,r不在乙個塊內,中間的塊裡二...
BZOJ3343 教主的魔法(分塊)
傳送門 正兒八經的分塊題。整個塊打add標記,其餘的暴力加。詢問的時候整個塊sort之後二分找,其餘的暴力找。include include include include include include using namespace std const int max n 1e6 5 const...
BZOJ3343 教主的魔法(分塊)
description 教主最近學會了一種神奇的魔法,能夠使人長高。於是他準備演示給xmyz資訊組每個英雄看。於是n個英雄們又一次聚集在了一起,這次他們排成了一列,被編號為1 2 n。每個人的身高一開始都是不超過1000的正整數。教主的魔法每次可以把閉區間 l,r 1 l r n 內的英雄的身高全部...