SGU 180 Inversions(离散化 + 线段树求逆序对)

题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=180

解题报告:一个裸的求逆序对的题,离散化+线段树,也可以用离散化+树状数组。因为这题中的数列有重复的而且范围特别大,所以要进行离散化,离散化的方法是,

首先按照输入的数字排个序,然后把整个数列扫一遍,得出每个数字离散化的结果,然后再按照输入的顺序把顺序调整回来就OK 了。线段树部分就不说了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 typedef __int64 INT;
 7 const int maxn = 65537+5;
 8 
 9 struct node
10 {
11     int data,cixu,dd;
12 }que[maxn];
13 
14 struct Node
15 {
16     INT data;
17     int l,r;
18 }tree[2*maxn];
19 
20 bool cmp1(node a,node b)
21 {
22     return a.data <= b.data;
23 }
24 bool cmp2(node a,node b)
25 {
26     return a.cixu < b.cixu;
27 }
28 void maketree(int p)
29 {
30     if(tree[p].l == tree[p].r)
31     return ;
32     int mid = (tree[p].l + tree[p].r) / 2;
33     tree[2*p].data = 0;
34     tree[2*p].l = tree[p].l;
35     tree[2*p].r = mid;
36     maketree(2*p);
37     tree[2*p+1].data = 0;
38     tree[2*p+1].l = mid + 1;
39     tree[2*p+1].r = tree[p].r;
40     maketree(2*p+1);
41 }
42 INT find(int p,int l,int r)
43 {
44     if(l >  r)
45     return 0;
46     if(tree[p].l == l && tree[p].r == r)
47     return tree[p].data;
48     int mid = (tree[p].l + tree[p].r) / 2;
49     if(r <= mid)
50     return find(2*p,l,r);
51     else if(l <= mid && r > mid)
52     return find(2*p,l,mid) + find(2*p+1,mid + 1,r);
53     else return find(2*p+1,l,r);
54 }
55 void push(int p,int d)
56 {
57     tree[p].data++;
58     if(tree[p].l == tree[p].r)
59     return ;
60     int mid = (tree[p].l + tree[p].r) / 2;
61     if(d <= mid)
62     push(2*p,d);
63     else push(2*p+1,d);
64 }
65 int main()
66 {
67     int n;
68     scanf("%d",&n);
69     for(int i = 1;i <= n;++i)
70     {
71         scanf("%d",&que[i].data);
72         que[i].cixu = i;
73     }
74     sort(que+1,que+n+1,cmp1);
75     int f = -1;
76     que[0].data = 0x7fffffff;   //只要一个跟所有输入的数都不同的就行了
77     for(int i = 1;i <= n;++i)
78     {
79         if(que[i].data != que[i-1].data)
80         f++;
81         que[i].dd = f;
82     }
83     tree[1].data = 0;
84     tree[1].l = 0;
85     tree[1].r = f;
86     maketree(1);
87     sort(que+1,que+n+1,cmp2);
88     INT tot = 0;
89     for(int i = 1;i <= n;++i)
90     {
91         tot += find(1,que[i].dd + 1,f);
92         push(1,que[i].dd);
93     }
94     printf("%I64d\n",tot);
95     return 0;
96 }
View Code

转载于:https://www.cnblogs.com/xiaxiaosheng/p/3850169.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值