zoukankan      html  css  js  c++  java
  • bzoj3744

    这道题是目前我做bzoj最感动的一题没有之一……
    首先先警示一下,分块的题目能不套主席树尽量不套
    因为主席树不仅回答来一个log而且常数也比较大,对于分块这种根号的算法非常不适合
    这里是求区间逆序对,考虑查询,不难想到答案是[l,r]所夹整块之间的逆序对数目和两边的数所带来的逆序对数目和
    首先第一部分是可以预处理出来的,算法是O(n*tot*logn)
    第二部分裸的想法是求每个数ai在区间[l,i]比它小的个数,然后可以用主席树搞搞
    但是不幸的是,这样直接T到死,自测bzoj第一点的数据就跑了24s……伤不起
    所以考虑bzoj2724的做法,我们还是先预处理f[i,j],g[i,j]表示1~i块内比j大的数和比j小的数的个数
    考虑两边的数ai,令它构成一个序列bj,这些数所带来的逆序对数目就是
    如果ai在整块左边,就是=[l,r]所夹整块内比它小的数个数,在整块右边就是=[l,r]所夹整块内比它大的数个数
    最后再加上bj序列的逆序对数目就是答案
    考虑一种快速计算逆序对的算法,不难想到用树状数组,这已经相当优
    下面就是令人感动的事情了,用树状数组替代主席树之后,程序已经能跑到28s左右
    想办法干掉fillchar并在调整一下块的大小,优化到了23,24s左右
    然后始终没能跑进20s……然后我就各种想,突然发现
    当l正好是一个块的左端点时,我的程序仍然遍历了l所在的块(很多分块的程序都是这样),其实可以没必要
    加了这个优化本地正好跑了20s,激动了,然后试着把r正好是块的右端点也特判一下
    王苍啊,终于过了,在bzoj上跑了18s……
    出题人大概是故意卡常数的吧……
    有幸成为这道题第一个pascal通过者,非常感动(苦逼的pascal伤不起啊)
    附上丑陋的代码:

      1 const maxn=50000;
      2 
      3 var s:array[0..300,0..300] of longint;
      4     f,g:array[0..300,0..maxn] of longint;
      5     co,v,a,be,b,c,rank,h:array[0..maxn] of longint;
      6     time,i,size,n,m,j,k,ans,x,y,t,tot,p:longint;
      7 
      8 function lowbit(x:longint):longint;
      9   begin
     10     exit(x and (-x));
     11   end;
     12 
     13 function min(a,b:longint):longint;
     14   begin
     15     if a>b then exit(b) else exit(a);
     16   end;
     17 
     18 procedure swap(var a,b:longint);
     19   var c:longint;
     20   begin
     21     c:=a;
     22     a:=b;
     23     b:=c;
     24   end;
     25 
     26 procedure add(x:longint);
     27   begin
     28     while x<=p do
     29     begin
     30       if v[x]<>time then
     31       begin
     32         c[x]:=0;
     33         v[x]:=time;
     34       end;
     35       inc(c[x]);
     36       x:=x+lowbit(x);
     37     end;
     38   end;
     39 
     40 function ask(x:longint):longint;
     41   begin
     42     ask:=0;
     43     while x>0 do
     44     begin
     45       if v[x]<>time then  //为了不用fillchar加了一个时间戳
     46       begin
     47         c[x]:=0;
     48         v[x]:=time;
     49       end;
     50       ask:=ask+c[x];
     51       x:=x-lowbit(x);
     52     end;
     53   end;
     54 
     55 procedure sort(l,r: longint);
     56   var i,j,x,y: longint;
     57   begin
     58     i:=l;
     59     j:=r;
     60     x:=b[(l+r) shr 1];
     61     repeat
     62       while b[i]<x do inc(i);
     63       while x<b[j] do dec(j);
     64       if not(i>j) then
     65       begin
     66         swap(b[i],b[j]);
     67         swap(h[i],h[j]);
     68         inc(i);
     69         j:=j-1;
     70       end;
     71     until i>j;
     72     if l<j then sort(l,j);
     73     if i<r then sort(i,r);
     74   end;
     75 
     76 function getans(l,r:longint):longint;
     77   var i,j,x:longint;
     78   begin
     79     getans:=0;
     80     t:=0;
     81     if be[r]=be[l] then
     82     begin
     83       for i:=l to r do
     84       begin
     85         getans:=getans+t-ask(rank[i]);
     86         add(rank[i]);
     87         inc(t);
     88       end;
     89     end
     90     else begin
     91       x:=min(be[r]*size,n);
     92       if ((be[l]-1)*size+1=l) and (x=r) then exit(s[be[l],be[r]])  //正好是端点可以直接计算
     93       else if ((be[l]-1)*size+1=l) then
     94       begin
     95         getans:=getans+s[be[l],be[r]-1];
     96         for i:=(be[r]-1)*size+1 to r do
     97         begin
     98           x:=rank[i];
     99           getans:=getans+f[be[r]-1,x]-f[be[l]-1,x];
    100           getans:=getans+t-ask(x);
    101           add(x);
    102           inc(t);
    103         end;
    104         exit;
    105       end
    106       else if (x=r) then
    107       begin
    108         getans:=getans+s[be[l]+1,be[r]];
    109         for i:=l to be[l]*size do
    110         begin
    111           x:=rank[i];
    112           getans:=getans+g[be[r],x]-g[be[l],x];
    113           getans:=getans+t-ask(x);
    114           add(x);
    115           inc(t);
    116         end;
    117         exit;
    118       end;
    119       getans:=getans+s[be[l]+1,be[r]-1];
    120       for i:=l to be[l]*size do
    121       begin
    122         x:=rank[i];
    123         getans:=getans+g[be[r]-1,x]-g[be[l],x];
    124         getans:=getans+t-ask(x);  //为了只调用一次查询
    125         add(x);
    126         inc(t);
    127       end;
    128       for i:=(be[r]-1)*size+1 to r do
    129       begin
    130         x:=rank[i];
    131         getans:=getans+f[be[r]-1,x]-f[be[l],x];
    132         getans:=getans+t-ask(x);
    133         add(x);
    134         inc(t);
    135       end;
    136     end;
    137   end;
    138 
    139 begin
    140   readln(n);
    141   size:=trunc(sqrt(n)/1.1);
    142   for i:=1 to n do
    143   begin
    144     read(a[i]);
    145     b[i]:=a[i];
    146     h[i]:=i;
    147     be[i]:=(i-1) div size+1;
    148   end;
    149   tot:=i div size;
    150   if i mod size<>0 then inc(tot);
    151   sort(1,n);
    152   p:=1;
    153   rank[h[1]]:=1;
    154   for i:=2 to n do
    155   begin
    156     if b[i]<>b[i-1] then inc(p);
    157     rank[h[i]]:=p;
    158   end;
    159   for i:=1 to tot do //预处理f[i,j],g[i,j]
    160   begin
    161     x:=min(i*size,n);
    162     for j:=(i-1)*size+1 to x do
    163       inc(co[rank[j]]);
    164     f[i,p]:=0;
    165     for j:=p-1 downto 1 do
    166       f[i,j]:=f[i,j+1]+co[j+1];
    167     g[i,1]:=0;
    168     for j:=2 to p do
    169       g[i,j]:=g[i,j-1]+co[j-1];
    170   end;
    171   for i:=1 to tot do  //预处理i~j块内的逆序对数
    172   begin
    173     t:=0;
    174     inc(time);
    175     for j:=(i-1)*size+1 to n do
    176     begin
    177       x:=t-ask(rank[j]);
    178       inc(s[i,be[j]],x);
    179       add(rank[j]);
    180       inc(t);
    181     end;
    182     for j:=i+1 to tot do
    183       s[i,j]:=s[i,j]+s[i,j-1];
    184   end;
    185   ans:=0;
    186   readln(m);
    187   for i:=1 to m do
    188   begin
    189     inc(time);
    190     readln(x,y);
    191     x:=x xor ans;
    192     y:=y xor ans;
    193     if x>y then swap(x,y);
    194     ans:=getans(x,y);
    195     writeln(ans);
    196   end;
    197 end.
    View Code
  • 相关阅读:
    MVC3 缓存应用
    centos下安装tomcat
    VS2010安装完SP1后再安装Silverlight Tools 4遇到的问题解决办法
    TOMCAT多站点配置
    C#.NET 添加图片水印
    装了vs11后运行MVC3程序出问题
    ASP.NET Session的七点认识
    C# 用正则取文本中所有链接
    Long time no blog...
    从程序员到项目经理(二)
  • 原文地址:https://www.cnblogs.com/phile/p/4473063.html
Copyright © 2011-2022 走看看