zoukankan      html  css  js  c++  java
  • bzoj2724

    分块大法好!
    首先预处理第i块到第j块的答案,这是可以在O(n*tot)内处理出来的 tot表示块数
    然后考虑询问对于[l,r],答案只可能是[l,r]之间所夹整块[i,j]的答案和非整块中的位置上的数
    下面我们要做的是快速求出一个数在区间[l,r]出现的次数
    当然我一无脑就直接写了主席树,这当然可以复杂度为O(size*logn)
    一开始TLE了,好来发现块大小为sqrt(n/log(n))最优,然后跑了20s就过了
    后来一想,不对,直接预处理每个数在块1..i出现的次数不就可以了吗
    这样求出一个数在区间[l,r]出现的次数只需要O(1)的时间,复杂度仅仅是O(size)
    好像是的……这样可以在O(nsqrt(n))的时间内搞出来,这次只跑了7s左右
    下面给出算法二

      1 const maxn=40010;
      2 
      3 var f:array[0..210,0..maxn] of longint;
      4     a1,a2:array[0..1010,0..1010] of longint;
      5     be,h,s,a,b,c,rank:array[0..maxn] of longint;
      6     ans,x,y,i,p,q,m,t,tot,size,n:longint;
      7 
      8 procedure swap(var a,b:longint);
      9   var c:longint;
     10   begin
     11     c:=a;
     12     a:=b;
     13     b:=c;
     14   end;
     15 
     16 procedure sort(l,r: longint);
     17   var i,j,x,y: longint;
     18   begin
     19     i:=l;
     20     j:=r;
     21     x:=b[(l+r) div 2];
     22     repeat
     23       while b[i]<x do inc(i);
     24       while x<b[j] do dec(j);
     25       if not(i>j) then
     26       begin
     27         swap(b[i],b[j]);
     28         swap(c[i],c[j]);
     29         inc(i);
     30         j:=j-1;
     31       end;
     32     until i>j;
     33     if l<j then sort(l,j);
     34     if i<r then sort(i,r);
     35   end;
     36 
     37 procedure clear(l,r:longint);
     38   var i:longint;
     39   begin
     40     for i:=l to r do
     41       s[rank[i]]:=-1;
     42   end;
     43 
     44 procedure pre;
     45   var i,j,p,q:longint;
     46   begin
     47     for i:=1 to tot do   //预处理在1..i的块中数出现的次数
     48     begin
     49       p:=i*size;
     50       if p>n then p:=n;
     51       for j:=(i-1)*size+1 to p do
     52         inc(s[rank[j]]);
     53       for j:=1 to m do
     54         f[i,j]:=s[j];
     55     end;
     56     for i:=1 to tot do  //预处理i~j块的答案
     57     begin
     58       p:=0;
     59       q:=2147483647;
     60       fillchar(s,sizeof(s),0);
     61       for j:=(i-1)*size+1 to n do
     62       begin
     63         inc(s[rank[j]]);
     64         if (s[rank[j]]>p) or ((s[rank[j]]=p) and (a[j]<q)) then
     65         begin
     66           p:=s[rank[j]];
     67           q:=a[j];
     68         end;
     69         a1[i,be[j]]:=p;
     70         a2[i,be[j]]:=q;
     71       end;
     72     end;
     73     fillchar(s,sizeof(s),255);
     74   end;
     75 
     76 function ask(x,y:longint):longint;
     77   var i,p,q,w:longint;
     78   begin
     79     if be[x]=be[y] then
     80     begin
     81       p:=0;
     82       q:=2147483647;
     83       for i:=x to y do
     84       begin
     85         if s[rank[i]]=-1 then s[rank[i]]:=0;
     86         inc(s[rank[i]]);
     87         if (s[rank[i]]>p) or (s[rank[i]]=p) and (a[i]<q) then
     88         begin
     89           p:=s[rank[i]];
     90           q:=a[i];
     91         end;
     92       end;
     93       clear(x,y);
     94       exit(q);
     95     end
     96     else begin
     97       p:=a1[be[x]+1,be[y]-1];
     98       q:=a2[be[x]+1,be[y]-1];
     99       for i:=x to be[x]*size do
    100       begin
    101         if s[rank[i]]=-1 then s[rank[i]]:=f[be[y]-1,rank[i]]-f[be[x],rank[i]];
    102         inc(s[rank[i]]);  //关键
    103         if (s[rank[i]]>p) or (s[rank[i]]=p) and (a[i]<q) then
    104         begin
    105           p:=s[rank[i]];
    106           q:=a[i];
    107         end;
    108       end;
    109       for i:=(be[y]-1)*size+1 to y do
    110       begin
    111         if s[rank[i]]=-1 then s[rank[i]]:=f[be[y]-1,rank[i]]-f[be[x],rank[i]];
    112         inc(s[rank[i]]);
    113         if (s[rank[i]]>p) or (s[rank[i]]=p) and (a[i]<q) then
    114         begin
    115           p:=s[rank[i]];
    116           q:=a[i];
    117         end;
    118       end;
    119       clear(x,be[x]*size);  //一点常数优化,不用fillchar
    120       clear((be[y]-1)*size+1,y);
    121       exit(q);
    122     end;
    123   end;
    124 
    125 begin
    126   readln(n,q);
    127   size:=trunc(sqrt(n));
    128   for i:=1 to n do
    129   begin
    130     read(a[i]);
    131     be[i]:=(i-1) div size+1;
    132     b[i]:=a[i];
    133     c[i]:=i;
    134   end;
    135   tot:=n div size;
    136   if n mod size<>0 then inc(tot);
    137   sort(1,n);
    138   m:=1;
    139   rank[c[1]]:=1;
    140   for i:=2 to n do
    141   begin
    142     if b[i]<>b[i-1] then inc(m);
    143     rank[c[i]]:=m;
    144   end;
    145   pre;
    146   t:=0;
    147   ans:=0;
    148   for i:=1 to q do
    149   begin
    150     readln(x,y);
    151     x:=(x+ans-1) mod n+1;
    152     y:=(y+ans-1) mod n+1;
    153     if x>y then swap(x,y);
    154     ans:=ask(x,y);
    155     writeln(ans);
    156   end;
    157 end.
    View Code



  • 相关阅读:
    设计模式--4建造者模式
    java中的方法重载与重写以及方法修饰符
    设计模式--3.模板方法模式
    设计模式--2.工厂方法模式
    设计模式--1.单例模式
    问题--时景某些用户不能发表评论解决方案
    EXCEL:从一组数据中查找我想要的某个数据是否存在
    Git版本控制--05--可以吃后悔药之版本回退
    Git版本控制--04--文件修改后怎么提交
    Git版本控制--03--怎么向Git仓库中添加文件
  • 原文地址:https://www.cnblogs.com/phile/p/4473064.html
Copyright © 2011-2022 走看看