这道题是目前我做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

 

posted on 2014-12-25 21:01  acphile  阅读(254)  评论(0编辑  收藏  举报