Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 46504 | Accepted: 16945 |
Description
Input
Output
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
求逆序数思路:首先初始化所有节点对应区间为0,然后优先插入最大值,并把最大值所在位置赋值为1,再查询插入位置前有多少个数(就是求1到 当前插入位置-1 之和),每次累加即是所有逆序对。
线段树(不用lazy思想)766ms:
#include
#include
#include
#define MAX 500000+10
#define LL long long
using namespace std;
int sum[MAX<<2];
struct record
{
int val, pos;
}num[MAX];
bool cmp(record a,record b)
{
return a.val > b.val;
}
void build(int o, int l, int r)//建树
{
sum[o] = 0;
if(l == r)
return ;
int mid = (l+r) >> 1;
build(o<<1, l, mid);
build(o<<1|1, mid+1, r);
}
int query(int o, int l, int r, int L, int R)//查询
{
if(L == l && R == r)
{
return sum[o];
}
int mid = (l+r) >> 1;
if(R <= mid) return query(o<<1, l, mid, L, R);
else if(L > mid) return query(o<<1|1, mid+1, r, L, R);
else return query(o<<1, l, mid, L, mid) + query(o<<1|1, mid+1, r, mid+1, R);
}
void update(int o, int l, int r, int L)//更新
{
sum[o] += 1;
if(l == r) return ;
int mid = (l+r) >> 1;
if(L <= mid) update(o<<1, l, mid, L);
else update(o<<1|1, mid+1, r, L);
}
int main()
{
int n, i;
LL ans;
while(scanf("%d", &n), n)
{
build(1, 1 ,n);
for(i = 0; i < n; i++)
{
scanf("%d", &num[i].val);
num[i].pos = i + 1;
}
sort(num, num+n, cmp);
ans = 0;
for(i = 0; i < n; i++)
{
update(1, 1, n, num[i].pos);
if(num[i].pos == 1)
continue;
ans += query(1, 1, n, 1, num[i].pos-1);
}
printf("%lld\n", ans);
}
return 0;
}
线段树+lazy 938ms:
#include
#include
#include
#define MAX 500000+10
#define LL long long
using namespace std;
int sum[MAX<<2];
struct record
{
int val, pos;
}num[MAX];
bool cmp(record a,record b)
{
return a.val > b.val;
}
void PushUp(int o)
{
sum[o] = sum[o<<1] + sum[o<<1|1];
}
void build(int o, int l, int r)//建树
{
sum[o] = 0;
if(l == r)
return ;
int mid = (l+r) >> 1;
build(o<<1, l, mid);
build(o<<1|1, mid+1, r);
PushUp(o);
}
int query(int o, int l, int r, int L, int R)//查询
{
if(L <= l && R >= r)
{
return sum[o];
}
int mid = (l+r) >> 1;
int res = 0;
if(L <= mid) res += query(o<<1, l, mid, L, R);
if(R > mid) res += query(o<<1|1, mid+1, r, L, R);
return res;
}
void update(int o, int l, int r, int L)//更新
{
if(l == r)
{
sum[o] += 1;
return ;
}
int mid = (l+r) >> 1;
if(L <= mid) update(o<<1, l, mid, L);
else update(o<<1|1, mid+1, r, L);
PushUp(o);
}
int main()
{
int n, i;
LL ans;
while(scanf("%d", &n), n)
{
build(1, 1 ,n);
for(i = 0; i < n; i++)
{
scanf("%d", &num[i].val);
num[i].pos = i + 1;
}
sort(num, num+n, cmp);
ans = 0;
for(i = 0; i < n; i++)
{
update(1, 1, n, num[i].pos);
if(num[i].pos == 1)
continue;
ans += query(1, 1, n, 1, num[i].pos-1);
}
printf("%lld\n", ans);
}
return 0;
}
树状数组 500ms:
#include
#include
#include
#define MAX 500000
#define LL long long
using namespace std;
int c[MAX];
int n;
struct record
{
int val, pos;//记录数值 和 位置
}num[MAX];
bool cmp(record a,record b)
{
return a.val > b.val;
}
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int s = 0;
while(x > 0)
{
s += c[x];
x -= lowbit(x);
}
return s;
}
void update(int x)
{
while(x <= n)
{
c[x] += 1;
x += lowbit(x);
}
}
int main()
{
int i, j;
LL ans;
while(scanf("%d", &n), n)
{
memset(c, 0, sizeof(c));
for(i = 0;i < n; i++)
{
scanf("%d", &num[i].val);
num[i].pos = i + 1;
}
sort(num, num+n, cmp);
ans = 0;
for(i = 0;i < n; ++i)//每一次插入当前最大值
{
update(num[i].pos);
ans += sum(num[i].pos-1);//统计前面有多少个数
}
printf("%lld\n", ans);
}
return 0;
}
归并排序:391ms
#include
#include
#define MAX 500000+10
#define LL long long
using namespace std;
int a[MAX], tmp[MAX];
LL ans;
void Merge(int l, int m, int r)
{
int i = l;
int j = m + 1;
int k = l;
while(i <= m && j <= r)
{
if(a[i] > a[j])
{
tmp[k++] = a[j++];
ans += m - i + 1;
}
else
{
tmp[k++] = a[i++];
}
}
while(i <= m) tmp[k++] = a[i++];
while(j <= r) tmp[k++] = a[j++];
for(int i = l; i <= r; i++)
{
a[i] = tmp[i];
}
}
void Merge_sort(int l,int r)
{
if(l < r)
{
int m = (l + r) >> 1;
Merge_sort(l,m);
Merge_sort(m+1,r);
Merge(l,m,r);
}
}
int main()
{
int n;
int i, j;
while(scanf("%d", &n),n)
{
for(i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
ans = 0;
Merge_sort(0,n-1);
printf("%lld\n", ans);
}
return 0;
}