HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4911

解题报告: 给出一个长度为n的序列,然后给出一个k,要你求最多做k次相邻的数字交换后,逆序数最少是多少?

因为每次相邻的交换操作最多只能减少一个逆序对,所以最多可以减少k个逆序对,所以我们只要求出原来的序列有多少个逆序对然后减去k再跟0取较大的就可以了。

因为数据范围是10的五次方,所以暴力求肯定会TLE,所以要用n*logn算法求逆序对,n*logn算法有几种可以求逆序对的:

线段树,树状数组,归并排序。

 

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

 

HDU 4911 http://acm.hdu.edu.cn/showproblem.php?pid=4911(线段树求逆序对),古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。