hud 2838 Cow Sorting 树状数组求逆序数

这道题纠结了很长时间0.0,今天早起重写了一发结果就a 了,Orz

主要原因还是算逆序数个数的时候没开long long,我还以为算sum的和的时候开long long 就好了,没想到光光是逆序数的个数就到达long long的级别了,下次还是要小心啊!

重写一次果然代码看起来清爽不少。大笑

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL __int64

struct nu {
    int x,t;
} num[100005];
LL n,sum[100005],cnt[100005],ans;

bool tmp(nu a,nu b) {
    return a.x > b.x;
}

int lowbit(int t) {  
    return t & (-t);
}

void getsum(int t,int x) {  //一个算逆序数的个数,另外一个算逆序数的和,就算是个数也要开long long
    LL cc = 0;
    while(t) {
        ans += sum[t];
        cc += cnt[t];
        t -= lowbit(t);
    }
    ans += cc*x;
}

void add(int t,int d,int x) { //两个一起加简洁点
    while(t <= n) {
        sum[t] += x;
        cnt[t] += d;
        t += lowbit(t);
    }
}

int main() {
    scanf("%I64d",&n);
        for(int i = 1;i <= n;i++) {
            scanf("%d",&num[i].x);
            num[i].t = i;
        }
        sort(num+1,num+1+n,tmp); //这种先排序再add进去算逆序数的方法还是不错的,不用考虑数据给的太大数组存不下
        memset(sum,0,sizeof(sum));
        memset(cnt,0,sizeof(cnt));
        ans = 0;
        for(int i = 1;i <= n;i++) {
            add(num[i].t,1,num[i].x);
            getsum(num[i].t-1,num[i].x);
        }
        printf("%I64d\n",ans);
    return 0;
}
加油!

在C语言中,我们可以使用经典的冒泡排序算法或更高效的插入排序、选择排序等方法来对整组(如`int a[]`)进行升序排序。这里我们以选择排序为例,因为它直观易懂,但效率并不是最高的。 **选择排序**的工作原理是每次从未排序的部分找到最小的元素,然后将其放到已排序部分的末尾。以下是选择排序的步骤: 1. 遍历整个组,找到最小的元素。 2. 将该元素与组的第一个元素交换位置。 3. 继续遍历剩余未排序的元素,重复第一步。 4. 当所有元素都被遍历过并放置在其正确的位置后,组就按照升序排列了。 以下是一个简单的选择排序示例: ```c #include <stdio.h> void selectionSort(int arr[], int n) { for (int i = 0; i < n - 1; i++) { // 遍历直到倒第二个元素 int minIndex = i; for (int j = i + 1; j < n; j++) { // 内层循环查找最小值 if (arr[j] < arr[minIndex]) { minIndex = j; // 更新最小索引 } } // 如果找到了最小值,就把它和当前位置的元素交换 if (minIndex != i) { int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } } } // 测试代码 int main() { int a[] = {5, 2, 9, 1, 7}; int n = sizeof(a) / sizeof(a[0]); printf("Before sorting: "); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); selectionSort(a, n); printf("After sorting: "); for (int i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); return 0; } ``` 运行这段代码,你会看到组`a`被按升序排序后的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值