1 #include<cstdio>
2 #include<algorithm>
3 using namespace std;
4 const int maxn=1e5+5;
5 int a[maxn];
6 int k[maxn];
7 struct note
8 {
9 int left, right, sum;
10 }tree[maxn*4];
11 void pushup(int id)
12 {
13 tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;
14 }
15 void build(int id, int l, int r)
16 {
17 tree[id].left=l; tree[id].right=r;
18 if(l==r) tree[id].sum=0;
19 else
20 {
21 int mid=(l+r)/2;
22 build(id<<1, l, mid);
23 build(id<<1|1, mid+1, r);
24 pushup(id);
25 }
26 }
27 int query(int id, int l, int r)
28 {
29 if(l<=tree[id].left && tree[id].right<=r)
30 {
31 return tree[id].sum;
32 }
33 else
34 {
35 int ans=0;
36 int mid=(tree[id].left+tree[id].right)/2;
37 if(l<=mid) ans+=query(id<<1, l, r);
38 if(r>mid) ans+=query(id<<1|1, l, r);
39 return ans;
40 }
41 }
42 void update(int id, int pos)
43 {
44 if(tree[id].left==tree[id].right)
45 {
46 tree[id].sum++;
47 }
48 else
49 {
50 int mid=(tree[id].left+tree[id].right)/2;
51 if(pos<=mid) update(id<<1, pos);
52 else update(id<<1|1, pos);
53 pushup(id);
54 }
55 }
56 int findk(int key, int n)查找对应位置的值。。。
57 {
58 int l=1, r=n;
59 while(l<=r)
60 {
61 int mid=(l+r)>>1;
62 if(k[mid]==key)
63 return mid;
64 else
65 {
66 if(key<k[mid])
67 r=mid-1;
68 else
69 l=mid+1;
70 }
71 }
72 }
73 int main()
74 {
75 int n, m=1;
76 scanf("%d", &n);
77 for(int i=1; i<=n; i++)
78 {
79 scanf("%d", &a[i]);
80 k[i]=a[i];
81 }
82 sort(k+1, k+1+n);
83 for(int i=2; i<=n; i++)去重
84 {
85 if(k[i]!=k[i-1])
86 k[++m]=k[i];
87 }
88 int t=m;
89 for(int i=1; i<=t-1; i++)弥补普通离散化的缺陷
90 {
91 if(k[i]+1!=k[i+1])
92 {
93 k[++m]=k[i]+1;
94 }
95 }
96 sort(k+1, k+1+m);
97 int ans=0;
98 build(1, 1, maxn);
99 for(int i=1; i<=n; i++)
100 {
101 ans+=query(1, findk(a[i], m)+1, maxn);
102 update(1, findk(a[i], m));
103 }
104 printf("%d", ans);
105
106 }
普通离散化缺点:
例子一:1-10 1-4 5-10
普通离散化后都变成了[1,4][1,2][3,4]
线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1被完全覆盖,而实际并没有覆盖。
解决方法:离散化时,要对相邻的数字,在离散化时中间加一个数字