小B的詢問

2022-04-30 19:21:09 字數 2055 閱讀 8307

這裡不講莫隊的思路,各路大神已經講清楚了。我們講一下如何卡常。

把正常的莫隊交上去,記錄。

單個點\(1784ms\)。

把每一次詢問的右邊界\(right[i]\)從小到大改為從打到小,快了了一點。注意要把陣列開小點。

\(1522ms\)。

如果分為\(trunc(sqrt(n))\)塊不好,然後分別試著分為\(n/6\)和\(n/10\)塊。

\(1178ms/795ms\)。

我們可以發現當\(div\)在這個時候時,越大,越快。記錄。

分別來看一下\(/20\)和\(/30\)的狀態:

\(533ms/618ms\)

記錄,整體沒有\(/10\)的優越。

綜合以上,我們\(/15\)。

得出記錄。

// luogu-judger-enable-o2

var node_num,i,j,n,m,l,r,sum,k:longint;

num:array[-1..51000] of longint;

id,left,right,recf,ans:array[-1..51000] of longint;

bucket:array[-1..51000] of longint;

procedure sort(l,r:longint);

var i,j,s,t:longint;

begin

i:=l; j:=r; s:=(l+r) div 2;

repeat

while ((recf[i]right[s]))) do inc(i);

while ((recf[j]>recf[s])or((recf[j]=recf[s])and(right[j]=j;

if il then sort(l,j);

end;

function locate(node:longint):longint;

begin

if node mod node_num=0 then

exit(node div node_num);

exit(node div node_num+1);

end;

procedure ready;

begin

read(n,m,k);

node_num:=n div 15;

for i:=1 to n do read(num[i]);

for i:=1 to m do

begin id[i]:=i; read(left[i],right[i]); recf[i]:=locate(left[i]); end;

sort(1,m);

end;

procedure add(x:longint);

begin

inc(bucket[x]);

inc(sum,bucket[x]*2-1);

end;

procedure dim(x:longint);

begin

dec(bucket[x]);

dec(sum,bucket[x]*2+1);

end;

begin

ready;

l:=1;

r:=0;

for i:=1 to m do

begin

while rright[i] do begin dim(num[r]); dec(r); end;

while lleft[i] do begin dec(l); add(num[l]); end;

ans[id[i]]:=sum;

end;

for i:=1 to m do

writeln(ans[i]);

end.

莫隊 小B的詢問

莫隊經典例題 這題詢問每一種數字數量的平方和,那麼我們在左移或右移的時候記錄一下就好了,當每一種數字的種類數加1或減1的時候,我們需要減去以前這個數對答案的影響,加上現在對答案的影響。假設原來數字a的種類數為k,如今又加入乙個a,那麼先ans k2,然後ans k 1 2.刪除同理。include ...

BZOJ 3781 小B的詢問

description 小b有乙個序列,包含n個1 k之間的整數。他一共有m個詢問,每個詢問給定乙個區間 l.r 求sigma c i 2 的值,其中i的值從1到k,其中c i 表示數字i在 l.r 中的重複次數。小b請你幫助他回答詢問。題目分析 分塊 include include include...

luogu P2709 小B的詢問

原題位置 這道題是莫隊,據說在離線區間查詢上,莫隊無敵,但是感覺還好吧 首先這道題是乙個用來練手的好題,因為這是板子題 所以主要就是排序,然後while查詢 至於排序方式 首先 應用分塊思想,以查詢左端點所在塊為第一關鍵字,以右端點為第二關鍵字 均從小到大排序 然後就沒有然後了 分割線啊 inclu...