您的位置:首页 > 其它

【树状数组】hdu 4911 Inversion(离散化+树状数组求逆序数)

2017-07-19 14:36 405 查看

Inversion

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 4183    Accepted Submission(s): 1525


[align=left]Problem Description[/align]

bobo has a sequence a1,a2,…,an. He is allowed to swap twoadjacent numbers for no more than k times.

Find the minimum number of inversions after his swaps.

Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and ai>aj.
 

[align=left]Input[/align]

The input consists of several tests. For each tests:

The first line contains 2 integers n,k (1≤n≤105,0≤k≤109). The second line contains n integers a1,a2,…,an (0≤ai≤109).
 

[align=left]Output[/align]

For each tests:

A single integer denotes the minimum number of inversions.
 

[align=left]Sample Input[/align]

3 1
2 2 1
3 0
2 2 1

 

[align=left]Sample Output[/align]

1
2

 
题意:给出n个数,每次可以交换相邻的两个数,最多交换k次,求交换后最小的逆序数是多少
分析:如果逆序数大于0,则存在1 ≤ i < n,使得交换ai和ai+1后逆序数减1。所以最后的答案就是max((inversion-k), 0)。利用树状数组求出原序列的逆序对数就可以解决问题了

注意:
因为数据比较大,因此肯定要用sort先排序
问题就在于相等的数怎么处理
如果你用的sort,就算你cmp里设定了相等的数不交换,
他也会交换?为什么?因为快排是不稳定的排序算法。
因此只用sort肯定会WA
别问我怎么知道的.....WA了一亿发... = =

解决办法用2个,一个使用stable_sort,这个跟sort用法一样,
但绝对不会改变相同的数的顺序

另外一个办法就是把相同的数字合并,或者说是删去计算即可


///AC代码(stable_sort版)
#include <iostream>
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <algorithm>
#include <functional>
#define PI acos(-1)
#define eps 1e-8
#define inf 0x3f3f3f3f
#define debug(x) cout<<"---"<<x<<"---"<<endl
typedef long long ll;
using namespace std;
const int N = 5e5 + 10;

struct  node
{
int val;
int pos;
} p
;
int n, k, a
, c
;

bool cmp(const node&a, const node& b)
{
return a.val < b.val;
}

int lowbit(int x)
{
return x & (-x);
}
///单点修改+区间求和
inline int sum(int x)
{
int res = 0;
while (x)
{
res += c[x], x -= lowbit(x);
}
return res;
}

inline void add(int x) ///单点修改
{
while (x <= n)
{
c[x] += 1, x += lowbit(x);
}
}

inline int query(int x, int y)///区间求和
{
return sum(y) - sum(x - 1);
}

int main()
{
while (scanf("%d%d", &n, &k) != EOF)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", &p[i].val);
p[i].pos = i;
}
stable_sort(p + 1, p + n + 1, cmp); ///排序
for (int i = 1; i <= n; i++)
{
a[p[i].pos] = i;        ///离散化
}

ll ans = 0;
for (int i = 1; i <= n; i++)///初始化树状数组
{
c[i] = 0;
}
for (int i = 1; i <= n; i++)
{
add(a[i]);
ans += i - sum(a[i]);
}

if (ans - k < 0)
{
printf("0\n");
}
else
{
printf("%lld\n", ans - k);
}
}
return 0;
}

///直接删除相同元素:
#include <iostream>
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <iomanip>
#include <cstring>
#include <algorithm>
#include <functional>
#define PI acos(-1)
#define eps 1e-8
#define inf 0x3f3f3f3f
#define debug(x) cout<<"---"<<x<<"---"<<endl
typedef long long ll;
using namespace std;
const int N = 5e5 + 10;

struct  node
{
int val;
int pos;
} p
;
int n, k, a
, c
;

bool cmp(const node&a, const node& b)
{
return a.val < b.val;
}

int lowbit(int x)
{
return x & (-x);
}
///单点修改+区间求和
inline int sum(int x)
{
int res = 0;
while (x)
{
res += c[x], x -= lowbit(x);
}
return res;
}

inline void add(int x) ///单点修改
{
while (x <= n)
{
c[x] += 1, x += lowbit(x);
}
}

inline int query(int x, int y)///区间求和
{
return sum(y) - sum(x - 1);
}

int main()
{
while (scanf("%d%d", &n, &k) != EOF)
{
for (int i = 1; i <= n; i++)
{
scanf("%d", &p[i].val);
p[i].pos = i;
}
//stable_sort(p + 1, p + n + 1, cmp); ///排序
sort(p + 1, p + n + 1, cmp);
p[0].val = -1;
int t = 0;
for (int i = 1; i <= n; i++)
{
if (p[i].val != p[i - 1].val)
{
t++;
}
a[p[i].pos] = t;        ///离散化
}

ll ans = 0;
for (int i = 1; i <= n; i++)///初始化树状数组
{
c[i] = 0;
}
for (int i = 1; i <= n; i++)
{
add(a[i]);
ans += i - sum(a[i]);
}

if (ans - k < 0)
{
printf("0\n");
}
else
{
printf("%lld\n", ans - k);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 hdu 函数