小B的询问

莫队

这里不讲莫队的思路,各路大神已经讲清楚了。我们讲一下如何卡常

\(Status\ 1\)

把正常的莫队交上去,记录

单个点\(1784ms\)

\(Status\ 2\)

把每一次询问的右边界\(right[i]\)从小到大改为从打到小,快了了一点。注意要把数组开小点。

\(1522ms\)

\(Status\ 3\)

如果分为\(trunc(sqrt(n))\)块不好,然后分别试着分为\(n/6\)\(n/10\)块。

\(1178ms/795ms\)

我们可以发现当\(div\)在这个时候时,越大,越快。记录

\(Status\ 4\)

分别来看一下\(/20\)\(/30\)的状态:

\(533ms/618ms\) 记录,整体没有\(/10\)的优越。

\(Status\ 5\)

综合以上,我们\(/15\)

得出记录

\(Code\)

// 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]<recf[s])or((recf[i]=recf[s])and(right[i]>right[s]))) do inc(i);
        while ((recf[j]>recf[s])or((recf[j]=recf[s])and(right[j]<right[s]))) do dec(j);
        if i<=j then
        begin
            t:=recf[i];  recf[i]:=recf[j];   recf[j]:=t;
            t:=id[i];    id[i]:=id[j];       id[j]:=t;
            t:=left[i];  left[i]:=left[j];   left[j]:=t;
            t:=right[i]; right[i]:=right[j]; right[j]:=t;
            inc(i); dec(j);
         end;
    until i>=j;
    if i<r then Sort(i,r);
    if j>l 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 r<right[i] do begin  inc(r); add(num[r]); end;
        while r>right[i] do begin dim(num[r]); dec(r); end;
        while l<left[i] do begin dim(num[l]); inc(l); end;
        while l>left[i] do begin dec(l); add(num[l]); end;
        ans[id[i]]:=sum;
    end;

    for i:=1 to m do
        writeln(ans[i]);
end.

posted @ 2018-09-23 15:13  _ARFA  阅读(124)  评论(0编辑  收藏  举报