BZOJ 3192: [JLOI2013]删除物品 奇淫技巧&树状数组

点我看题

这题十分奇淫技巧...QAQ因为知道是树状数组的题QAQ刚开始以为维护两个数组的树状数组然后模拟从大到小,然后发现不会打QAQ

于是悄悄咪咪翻开题解了。

实际上两个数组可以看做一个数组

如  1 4 5 

           2 7 3

实际上就是 5 4 1 | 2 7 3

    “|”这个地方就是假设成一个指标,然后每次把这个指标移到某一个位置,这个位置左右两个边的数就可以删除。

   所以就模拟从大到小删数。

  第一次 5 4 1 2 | 7 3

指标移动1次就可以删掉“7”   

第二次   5 | 4 1 2 3

指标移动3次就可以删掉“5”

第三次   |4 1 2 3

 指标不需要移动就可以删除“4”

......

然后就把这些移动的次数加起来就是答案~(≧▽≦)/~啦啦啦

把删掉的数的位置 置0 有数的位置 置1 然后树状数组维护一下就好了~

 1 var a,c,tree:array[0..200500]of int64;
 2     i,n,m,p:longint;
 3     x,ans:int64;
 4 
 5 procedure qs(l,r:longint);
 6 var i,j:longint;
 7     m,t:int64;
 8 begin
 9   i:=l;
10   j:=r;
11   m:=a[(l+r)>>1];
12   repeat
13     while a[i]>m do inc(i);
14     while a[j]<m do dec(j);
15     if i<=j then
16     begin
17       t:=a[i];a[i]:=a[j];a[j]:=t;
18       t:=c[i];c[i]:=c[j];c[j]:=t;
19       inc(i);
20       dec(j);
21     end;
22   until i>j;
23   if l<j then qs(l,j);
24   if i<r then qs(i,r);
25 end;
26 function low(x:longint):longint;
27 begin
28   exit(x and -x);
29 end;
30 procedure adde(x,d:longint);
31 begin
32   while x<=p do
33   begin
34     inc(tree[x],d);
35     inc(x,low(x));
36   end;
37 end;
38 function sum(x:longint):int64;
39 var s:int64;
40 begin
41   s:=0;
42   while x>0 do
43   begin
44     inc(s,tree[x]);
45     dec(x,low(x));
46   end;
47   exit(s);
48 end;
49 begin
50   read(n,m);
51   p:=n+m;
52   for i:=n downto 1 do
53   begin
54     read(a[i]);
55     c[i]:=i;
56     adde(i,1);
57   end;
58   for i:=n+1 to p do
59   begin
60     read(a[i]);
61     c[i]:=i;
62     adde(i,1);
63   end;
64   qs(1,p);
65   if c[1]>n then x:=n+1 else x:=n;
66   ans:=0;
67   for i:=1 to p do
68   begin
69     adde(c[i],-1);
70     if c[i]>x then ans:=ans+sum(c[i])-sum(x-1) else
71                    ans:=ans+sum(x)-sum(c[i]-1);
72     x:=c[i];
73   end;
74   writeln(ans);
75 end.
BZOJ3192