POJ3378 Crazy Thairs
魂之挽歌原创,转载请注明出处:
http://www.cnblogs.com/whitecloth
【题目大意】
给你一个序列,求其中长度为5的递增序列的个数(N<=50000)
【题目分析】
方案数可能达到的最大值:C(50000,3)=2603645869790625010000 >2^64-1,所以这个题要用高精度。
本题要求求出方案数,让人不免往USACO的buylow那里想,但buylow算法的复杂度是N^2的,此方法不可解。
然后想,搞4个二叉搜索树进行插入和统计操作,然后,好不容易调出来,交上去超时了,然后高精度压位,还是超时,要是改成平衡树旋转也会耗费很多额外的代价,速度不会优化多少(自己感觉,没试过)。
最后再想,就想到树状数组了,用树状数组来统计一个数前面比它小的数的个数还是很方便的。这样我们先对序列进行离散化,然后搞4个树状数组出来,用c[i,j]表示第i个树状数组里第j位存储的方案数,那么对于一个数k,以它结尾的长度为i的方案数就是c[i-1,1..s[k]-1],其中s[k]是离散化过的序列。(具体实现时c[i,j]为高精度数字)
还是超时,再压位,终于2536ms水过去了……
【代码实现】
Code
1 program poj3378;
2 type int128=array[0..10]of longint;
3 var a,p:array[0..50000]of longint;
4 s:array[0..50000]of longint;
5 c:array[0..5,0..50000]of int128;
6 ans,b:int128;
7 i,j,k,n:longint;
8 function plus(a,b:int128):int128;
9 var l,i:longint;
10 c:int128;
11 begin
12 l:=10;
13 while (a[l]+b[l]=0)and(l>1) do dec(l);
14 fillchar(c,sizeof(c),0);
15 for i:=1 to l do
16 begin
17 inc(c[i],a[i]+b[i]);
18 c[i+1]:=c[i] div 10000;
19 c[i]:=c[i] mod 10000;
20 end;
21 exit(c);
22 end;
23 function lowbit(x:longint):longint;
24 begin
25 exit(x and(-x));
26 end;
27 procedure insert(i,j:longint);
28 var k:longint;
29 begin
30 k:=j;
31 while k<=n do
32 begin
33 c[i,k]:=plus(c[i,k],b);
34 k:=k+lowbit(k);
35 end;
36 end;
37 function get(i,j:longint):int128;
38 var a:int128;
39 k:longint;
40 begin
41 k:=j;
42 fillchar(a,sizeof(a),0);
43 while k<>0 do
44 begin
45 a:=plus(a,c[i,k]);
46 k:=k-lowbit(k);
47 end;
48 exit(a);
49 end;
50 procedure kp(l,r:longint);
51 var i,j,x,y:longint;
52 begin
53 i:=l;j:=r;
54 x:=a[(l+r)shr 1];
55 repeat
56 while a[i]<x do inc(i);
57 while a[j]>x do dec(j);
58 if i<=j then
59 begin
60 y:=a[i];a[i]:=a[j];a[j]:=y;
61 y:=p[i];p[i]:=p[j];p[j]:=y;
62 inc(i);
63 dec(j);
64 end;
65 until i>j;
66 if l<j then kp(l,j);
67 if i<r then kp(i,r);
68 end;
69 begin
70 while not seekeof do
71 begin
72 fillchar(c,sizeof(c),0);
73 fillchar(ans,sizeof(ans),0);
74 readln(n);
75 for i:=1 to n do
76 begin
77 read(a[i]);
78 p[i]:=i;
79 end;
80 readln;
81 kp(1,n);
82 s[p[1]]:=1;
83 for i:=2 to n do
84 if a[i]=a[i-1] then s[p[i]]:=s[p[i-1]]
85 else s[p[i]]:=s[p[i-1]]+1;
86 for i:=1 to n do
87 begin
88 fillchar(b,sizeof(b),0);
89 b[1]:=1;
90 insert(1,s[i]);
91 for k:=2 to 4 do
92 begin
93 b:=get(k-1,s[i]-1);
94 insert(k,s[i]);
95 end;
96 ans:=plus(ans,get(4,s[i]-1));
97 end;
98 i:=10;
99 while (ans[i]=0)and(i>1) do dec(i);
100 for j:=i downto 1 do
101 begin
102 if (ans[j]<1000)and(j<>i) then write(0);
103 if (ans[j]<100)and(j<>i) then write(0);
104 if (ans[j]<10)and(j<>i) then write(0);
105 write(ans[j]);
106 end;
107 writeln;
108 end;
109 end.