2011 Heilongjiang collegiate programming contest - Problem H - Car race game

本文深入解析了两种用于计算数列逆序数的复杂度为O(nlogn)的算法:树状数组与归并排序。通过离散化处理与优化技巧,实现快速准确地统计逆序数,旨在提升数据结构与算法领域的实践效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

求数列逆序数复杂度O(nlogn)的两种算法

1. 树状数组,对于大数据需要进行离散化处理

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <stack>
#define INF (int)(1e9)
#define maxn 1000010
#define Lson l, mid, rt << 1
#define Rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long ll;
struct node {
    int x, v;
    bool operator < (const node &g) const {
        if (x != g.x) return x < g.x;
        return v > g.v;
    }
}no[maxn];
int num[maxn << 1], n;
int lowbit(int x) {return x&(-x);}
void update(int x, int v) {
    for (; x <= maxn; x += lowbit(x)) {
        num[x] += v;
    }
}
ll query(int x) {
    ll ret = 0;
    for (; x > 0; x -= lowbit(x)) {
        ret += ll(num[x]);
    }
    return ret;
}
int main() {
    while (scanf("%d", &n) != EOF) {
        memset(num, 0, sizeof(num));
        for (int i = 1; i <= n; ++ i) {
            scanf("%d%d", &no[i].x, &no[i].v);
        }
        sort(no+1, no+n+1);
        ll res = 0;
        for (int i = 1; i <= n; ++ i) {
            update(no[i].v,1);
            res += (i - query(no[i].v));
        }
        printf("%lld\n", res);

    }
}

2. 归并排序同时求出逆序数

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <stack>
#define INF (int)(1e9)
#define maxn 1000010
#define Lson l, mid, rt << 1
#define Rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long ll;
struct P {
    int a,b;
} s[1100005],t[1100005];
bool cmp (P a, P b) {
    if (a.a != b.a) return a.a < b.a;
    return a.b > b.b;
}
ll ans;
void merge_sort(P* A, int x, int y, P *T) {
    if (y - x > 1) {
        int m = (y + x) >> 1;
        int p = x, q = m, i = x;
        merge_sort(A, x, m, T);
        merge_sort(A, m, y, T);
        while (p < m || q < y) {
            if(q >= y || (p < m && A[p].b <= A[q].b)) {
                T[i++] = A[p++];
            } else {
                T[i++] = A[q++];
                ans += ll(m-p);
            }
        }
        for (i = x; i < y; i ++)
            A[i] = T[i];
    }
}
int main() {
    int n;
    while (cin >> n) {
        memset(s, 0, sizeof(s));
        memset(t, 0, sizeof(t));
        for(int i = 0; i < n; ++ i) {
            scanf("%d%d", &s[i].a, &s[i].b);
        }
        sort(s, s+n, cmp);
        ans = 0;
        merge_sort(s, 0, n, t);
        cout << ans << endl;
    }
    return 0;
}


<think>好的,我现在需要帮助用户解决在Matlab中对两个Excel文件进行小波相干性分析,并为四个省份生成独立图表的问题。首先,我得理清用户的具体需求。 用户提到的是NDVI_1和SPEI_1_sisheng两个Excel文件,需要分析它们的小波相干性,并分别生成黑龙江、吉林、辽宁、内蒙古四个省份的图表。首先,我需要确认这两个文件的数据结构。通常,Excel文件可能包含不同省份的数据,可能按列或行排列。用户可能需要按省份提取数据,然后进行小波分析。 接下来,我需要考虑如何在Matlab中读取Excel数据。使用readtable函数是比较常见的方法,可以指定范围或工作表。用户可能需要确保数据列的正确对应,比如时间序列数据可能位于某一列,而各省份的数据在后续列中。 然后是数据预处理部分。小波分析通常需要连续的时间序列,所以需要检查是否有缺失值,并进行插值处理。同时,时间数据可能需要转换为Matlab的日期格式,比如datetime类型,方便后续处理。 关于小波相干性分析,Matlab的小波工具箱中有现成的函数wcoherence。需要确认用户是否安装了该工具箱。如果没有,可能需要提示用户安装或寻找替代方法。该函数需要两个时间序列作为输入,并返回相干性结果以及频率和时间信息。 生成图表部分,用户需要四个省份的独立图表。因此,在代码中需要循环处理每个省份的数据,提取对应的NDVI和SPEI列,进行小波分析,然后绘图。每个省份的图表需要单独保存,可能用省份名称命名文件,比如'heilongjiang_coherence.png'。 在绘图时,需要注意设置标题、坐标轴标签,调整颜色映射以清晰显示相干性结果。可能还需要调整时间轴的显示格式,确保日期正确呈现。此外,使用subplots或其他布局方式可能需要调整,但用户要求的是四张独立图表,因此每个循环迭代生成一个新图并保存,避免覆盖。 可能遇到的问题包括数据列名的不一致,需要用户根据实际Excel文件调整代码中的变量名。另外,时间列的格式可能不同,需要用户确认时间数据的读取是否正确。还有,小波相干性分析的参数设置,比如采样周期(这里假设是月度数据,所以samplingPeriod设为1),可能需要根据实际情况调整。 最后,代码的结构需要清晰,方便用户修改和调试。添加注释是个好习惯,帮助用户理解每一步的操作。同时,需要提示用户可能需要调整的部分,比如文件路径、工作表名称、数据范围等。 总结步骤: 1. 读取两个Excel文件的数据。 2. 按省份提取NDVI和SPEI的时间序列。 3. 预处理数据,处理缺失值,转换时间格式。 4. 对每个省份进行小波相干性分析。 5. 生成并保存独立的图表。 6. 处理可能的异常情况,如数据不存在或格式错误。 需要验证代码的正确性,比如使用示例数据测试,确保每个步骤无误。同时,提醒用户注意Matlab工具箱的安装和文件路径的正确设置。</think>根据您的要求,我为您编写了完整的Matlab小波相干性分析代码实现,并按省份生成独立图表。以下是分步说明和完整代码: ```matlab %% 步骤1:读取Excel数据 ndvi_data = readtable('NDVI_1.xlsx', 'Sheet', 'Sheet1'); % 修改为实际工作表名 spei_data = readtable('SPEI_1_sisheng.xlsx', 'Sheet', 'Sheet1'); %% 步骤2:定义省份列表和时间序列 provinces = {'黑龙江', '吉林', '辽宁', '内蒙古'}; time = datetime(ndvi_data.Year, 1, 1); % 假设年份存储在Year列 %% 步骤3:预处理参数设置 samplingPeriod = 1; % 假设是年度数据(单位:年) waveletName = 'amor'; % 使用Morlet小波 colorLimits = [0 1]; % 相干性取值范围 %% 步骤4:小波相干性分析主循环 for i = 1:length(provinces) % 提取当前省份数据 province = provinces{i}; ndvi = ndvi_data.(province); spei = spei_data.(province); % 数据预处理 validIdx = ~isnan(ndvi) & ~isnan(spei); time_clean = time(validIdx); ndvi_clean = ndvi(validIdx); spei_clean = spei(validIdx); % 小波相干性计算 [wcoh, ~, period, coi] = wcoherence(ndvi_clean, spei_clean,... seconds(samplingPeriod*365.25*24*3600), 'Wavelet', waveletName); % 可视化设置 figure('Position', [100 100 800 600], 'Visible', 'off'); h = pcolor(time_clean, log2(period), abs(wcoh).^2); h.EdgeColor = 'none'; hold on; plot(time_clean, log2(coi), 'w--', 'LineWidth', 2); % 坐标轴设置 ylabel('周期(年)'); yt = 2.^unique(round(log2(period))); yticks(log2(yt)); yticklabels(num2str(yt', '%g')); xlabel('时间'); title([province ' NDVI-SPEI小波相干性']); colormap jet; caxis(colorLimits); colorbar; % 保存图像 exportgraphics(gcf, [province '_coherence.png'], 'Resolution', 300); close(gcf); end ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值