Thair数 树状数组

题目:

Erwin最近对一种叫"thair"的东西巨感兴趣。。。

在含有n个整数的序列a1,a2......an中,

三个数被称作"thair"当且仅当i<j<k且ai<aj<ak

求一个序列中"thair"的个数。

Input (thair.in)

开始一个正整数n,

以后n个数a1~an

Output (thair.out)

"thair"的个数

Sample











Input

Output

4

2 1 3 4

2

5

1 2 2 3 4

7

对样例2的说明:

7个"thair"分别是

1 2 3

1 2 4

1 2 3

1 2 4

1 3 4

2 3 4

2 3 4

约定

30%的数据n<=100

60%的数据n<=2000

100%的数据n<=30000

大数据随机生成

0<=a[i]<=maxlongint

首先分析题目,对于任意一个数a[i],它前面的每一个数都可以与后面所有比a[i]大的数形成Thair数,记第i个数前面比它小的数的个数为b[i],后面比它小的数的个数为c[i],那么最后的答案就是Σ(b[i]
*
c[i])。至于统计个数,由于n到30000,O(n^2)肯定不可行,所以我们用个树状数组就可以降低时间复杂度。而且由于要用到树状数组,但a[i]可能很大,在做之前要先将其离散化。下面是代码


  1 //By Neil
2 program Thair;
3 const
4 maxN =30000 + 100;
5 var
6 bit :array[0..maxN] of longint;
7 i,j,k,l,m,n :longint;
8 a,b,c :array[0..maxN] of longint;
9 num,p :array[0..maxN] of longint;
10 tot :longint;
11 ans :int64;
12
13 procedure swap(var x,y:longint);
14 var
15 tmp :longint;
16 begin
17 tmp := x;
18 x := y;
19 y := tmp;
20 end;
21
22 procedure qs(l,r:longint);
23 var
24 i,j,k :longint;
25 begin
26 i := l;
27 j := r;
28 k := a[(i + j) div 2];
29 repeat
30 while a[i] < k do inc(i);
31 while a[j] > k do dec(j);
32 if i <= j then
33 begin
34 swap(a[i],a[j]);
35 swap(num[i],num[j]);
36 inc(i);
37 dec(j);
38 end;
39 until (i > j);
40 if i < r then qs(i,r);
41 if l < j then qs(l,j);
42 end;
43
44 procedure add(x :longint);
45 begin
46 while (x <= maxN) do
47 begin
48 inc(bit[x]);
49 inc(x,x and (-x));
50 end;
51 end;
52
53 function ask(x :longint):longint;
54 var
55 ret :longint;
56 begin
57 ret := 0;
58 while (x > 0) do
59 begin
60 inc(ret,bit[x]);
61 dec(x,x and (-x));
62 end;
63 exit(ret);
64 end;
65
66 procedure init;
67 begin
68 read(n);
69 for i := 1 to n do
70 begin
71 read(a[i]);
72 num[i] := i;
73 end;
74 qs(1,n);
75 a[0] := - maxlongint;
76 tot := 0;
77 for i := 1 to n do
78 if a[i] > a[i - 1] then
79 begin
80 inc(tot);
81 c[num[i]] := tot;
82 end
83 else
84 c[num[i]] := tot;
85 end;
86
87 procedure main;
88 begin
89 fillchar(a,sizeof(a),0);
90 for i := 1 to n do
91 begin
92 inc(a[i],ask(c[i] - 1));
93 add(c[i]);
94 end;
95 fillchar(bit,sizeof(bit),0);
96 for i := n downto 1 do
97 begin
98 inc(b[i],n - i - ask(c[i]));
99 add(c[i]);
100 end;
101 for i := 1 to n do inc(ans,a[i] * b[i]);
102 writeln(ans);
103 end;
104
105 begin
106 assign(input,‘Thair.in‘);
107 reset(input);
108 assign(output,‘Thair.out‘);
109 rewrite(output);
110 init;
111 main;
112 close(input);
113 close(output);
114 end.

Thair数 树状数组,码迷,mamicode.com

时间: 2024-12-30 02:33:26

Thair数 树状数组的相关文章

hdu 4911 求逆序对数+树状数组

http://acm.hdu.edu.cn/showproblem.php?pid=4911 给定一个序列,有k次机会交换相邻两个位置的数,问说最后序列的逆序对数最少为多少. 实际上每交换一次能且只能减少一个逆序对,所以问题转换成如何求逆序对数. 归并排序或者树状数组都可搞 树状数组: 先按大小排序后分别标号,然后就变成了求1~n的序列的逆序数,每个分别查询出比他小的用i减,在把他的值插入即可 #include <cstdio> #include <cstdlib> #includ

求序列中满足Ai &lt; Aj &gt; Ak and i &lt; j &lt; k的组数 树状数组 HIT 2275 Number sequence

http://acm.hit.edu.cn/hoj/problem/view?id=2275 Number sequence   Source : SCU Programming Contest 2006 Final   Time limit : 1 sec   Memory limit : 64 M Submitted : 1632, Accepted : 440 Given a number sequence which has N element(s), please calculate

树状数组的另一种用法(离散化存数)

这个操作就是对每一个数加完之后add( x , k ),再将这个数减回去add(x+1 , k)的一个操作,执行完这个操作之后,树状数组里存的就不再是一段的和了而是每个数的离散. 这样对于你要对一个区间(x,y)添加一个数k的话,只需要add(x , k)然后对y后边的数剪去k.add(y+1 , -k)注意是-k,我们就讲这个区间的每一个数都添加进了这个区间了. 求和的话,只能求一个数x,因为树状数组不再是全部数的和了,从x到1的lobit加起来才是x这个数的值. 直接把洛谷的模板题搬出来用:

hdu4417 树状数组(求指定区间比指定数小的数的个数)

http://acm.hdu.edu.cn/showproblem.php?pid=4417 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in our memory. Now the poor princess is in trouble again and Mario needs to save his lover.

1144 数星星 (树状数组)

1144 数星星 该题有题解 时间限制:564MS  内存限制:65536K提交次数:193 通过次数:43 题型: 编程题   语言: G++;GCC Description 天文学家们喜欢观察星星.它们把每颗星星看成一个点,并把每颗星星左下方(即横坐标和纵坐标都不比它大)的星星颗数作为它的等级值. 现给出所有星星(星星个数为N)的坐标,计算并输出指定编号的星星的等级. 注意:不存在相同坐标的星星 输入格式 第一行为N 后N行为编号为1到N的星星的坐标(坐标用整数) 此后是M 后一行是M个星星

树状数组的进阶运用(Stars 数星星)

英文原题 Problem Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coordinates. Let the level of a star be an amount of the stars that are not higher and not to the right of the g

树状数组+逆序数与顺序数——HDU 2492

对应HDU题目:点击打开链接 Ping pong Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Description N(3N20000) ping pong players live along a west-east street(consider the street as a line segment). Each player has a unique skil

hdu 2838 Cow Sorting 树状数组求所有比x小的数的个数

Cow Sorting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4766    Accepted Submission(s): 1727 Problem Description Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening.

求序列A中每个数的左边比它小的数的个数(树状数组)

给定一个有N个正整数的序列A(N<=10^5,A[i]<=10^5),对序列中的每一个数,求出序列中它左边比它小的数的个数. 思路:树状数组的经典应用(裸题) 1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 5 using namespace std ; 6 7 const int N = 100010 ; 8 9 int c[N] ; 10 11 int lowbit(