HDU2838 Cow Sorting【树状数组】【逆序数】
2015-04-28 17:05
190 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2838
题目大意:
有N头奶牛排成一排。每头奶牛都有一个唯一的"坏脾气"值。坏脾气的范围为1~100000。现在将
奶牛重新排序,使奶牛按照坏脾气增加的顺序排列。所有的奶牛都可以相互交换位置。但是交换脾
气值为X,Y的两头奶牛,需要的时间是X+Y。现在问:将奶牛重新排列需要的最短时间是多少。
思路:
这道题就是给你一个N个元素的序列,求这个序列中所有逆序数的和。所以,对于值为a的第i个元素,
除了知道前i个元素里比a大的元素个数之外,还得知道前i个元素里比a大的元素的和。建立结构体树
状数组,一个变量来记录比a小的元素个数,i -比a小的元素个数就是前i个元素里比a大的元素个数(即
逆序数的个数),这样是为了方便计算。另一个变量来记录比a小的元素的和。n个数的和-比a小的元素
和就是之前比a大的数的和。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
const int MAXN = 100010;
struct Node
{
int Cnt; //记录前i个元素里比a大的元素个数
LL sum; //记录前i个元素里比a大的元素的和
}Tree[MAXN];
int N;
int Lowbit(int i)
{
return i & (-i);
}
void Update(int i,int v,int Cnt)
{
while(i <= N)
{
Tree[i].sum += v;
Tree[i].Cnt += Cnt;
i += Lowbit(i);
}
}
int QueryCnt(int n) //返回值为a的数前边比a小的元素个数
{
int ans = 0;
while(n > 0)
{
ans += Tree
.Cnt;
n -= Lowbit(n);
}
return ans;
}
LL QuerySum(int n) //返回值为a的数前边比a小的元素的和
{
LL ans = 0;
while(n > 0)
{
ans += Tree
.sum;
n -= Lowbit(n);
}
return ans;
}
int main()
{
int a;
while(cin >> N)
{
LL ans = 0;
memset(Tree,0,sizeof(Tree));
for(int i = 1; i <= N; ++i)
{
cin >> a;
Update(a,a,1);
LL k1 = i - QueryCnt(a); //k1值为a的第i个元素的逆序对
if(k1 != 0)
{
//值为a的数之前比a大的数的总和
LL k2 = QuerySum(N) - QuerySum(a);
ans += k1*a + k2;
}
}
cout << ans << endl;
}
return 0;
}
http://acm.hdu.edu.cn/showproblem.php?pid=2838
题目大意:
有N头奶牛排成一排。每头奶牛都有一个唯一的"坏脾气"值。坏脾气的范围为1~100000。现在将
奶牛重新排序,使奶牛按照坏脾气增加的顺序排列。所有的奶牛都可以相互交换位置。但是交换脾
气值为X,Y的两头奶牛,需要的时间是X+Y。现在问:将奶牛重新排列需要的最短时间是多少。
思路:
这道题就是给你一个N个元素的序列,求这个序列中所有逆序数的和。所以,对于值为a的第i个元素,
除了知道前i个元素里比a大的元素个数之外,还得知道前i个元素里比a大的元素的和。建立结构体树
状数组,一个变量来记录比a小的元素个数,i -比a小的元素个数就是前i个元素里比a大的元素个数(即
逆序数的个数),这样是为了方便计算。另一个变量来记录比a小的元素的和。n个数的和-比a小的元素
和就是之前比a大的数的和。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define LL __int64
using namespace std;
const int MAXN = 100010;
struct Node
{
int Cnt; //记录前i个元素里比a大的元素个数
LL sum; //记录前i个元素里比a大的元素的和
}Tree[MAXN];
int N;
int Lowbit(int i)
{
return i & (-i);
}
void Update(int i,int v,int Cnt)
{
while(i <= N)
{
Tree[i].sum += v;
Tree[i].Cnt += Cnt;
i += Lowbit(i);
}
}
int QueryCnt(int n) //返回值为a的数前边比a小的元素个数
{
int ans = 0;
while(n > 0)
{
ans += Tree
.Cnt;
n -= Lowbit(n);
}
return ans;
}
LL QuerySum(int n) //返回值为a的数前边比a小的元素的和
{
LL ans = 0;
while(n > 0)
{
ans += Tree
.sum;
n -= Lowbit(n);
}
return ans;
}
int main()
{
int a;
while(cin >> N)
{
LL ans = 0;
memset(Tree,0,sizeof(Tree));
for(int i = 1; i <= N; ++i)
{
cin >> a;
Update(a,a,1);
LL k1 = i - QueryCnt(a); //k1值为a的第i个元素的逆序对
if(k1 != 0)
{
//值为a的数之前比a大的数的总和
LL k2 = QuerySum(N) - QuerySum(a);
ans += k1*a + k2;
}
}
cout << ans << endl;
}
return 0;
}
相关文章推荐
- hdu2838 Cow Sorting(树状数组)
- HDOJ 题目2838 Cow Sorting(树状数组逆序对)
- HDU2838 Cow Sorting (树状数组)
- HDU - 2838 Cow Sorting (树状数组 + 逆序对)
- HDU - 2838 Cow Sorting解题报告(树状数组求逆序数相关+技巧)
- hdu_2838_Cow Sorting(树状数组求逆序对)
- hdu_2838_Cow Sorting(树状数组求逆序对)
- 树状数组 hdu2838 Cow Sorting
- 树状数组总结——详解(单点/区间查询, 单点/区间修改, 逆序对)
- 【BestCoder Round 65C】【树状数组 动态查找第k大 O(nlogn)】ZYB's Premutation 告诉你前i个数中的逆序对数让你还原全排列
- Inversion (hdu 4911 树状数组 || 归并排序 求逆序对)
- hdu_2688_Cow Sorting(树状数组)
- HDU1394用树状数组求逆序数
- poj 2299 树状数组求逆序对数+离散化
- [BZOJ] 2141 - Atlantis - 排队 - 树状数组求逆序对 - 分块求区间比 k 小
- POJ2299 树状数组求逆序数
- Ultra-QuickSort---poj2299 (归并排序.逆序数.树状数组.离散化)
- POJ2299 Ultra-QuickSort【树状数组】【逆序数】
- PKU 2299 【逆序数+树状数组】
- poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】