区间最大频率

ACM模版

区间最大频率

参考题目链接:
POJ 3368 Frequent values

/*
 *  求区间中数出现的最大频率
 *  方法一:线段树.
 *  先离散化。因为序列是升序,所以先将所有值相同的点缩成一点。这样n规模就缩小了。建立一个数据结构
 *  记录缩点的属性:在原序列中的值id,和该值有多少个num比如序列
 *  10
 *  -1 -1 1 1 1 1 3 10 10 10
 *  缩点后为:下标 1 2 3 4
 *          id -1 1 3 10
 *         num  2 4 1 3
 *  然后建树,树的属性有区间最大值(也就是频率)和区间总和。
 *  接受询问的时候。接受的是原来序列的区间[be,ed]我们先搜索一下两个区间分别在离散化区间后的下标。
 *  比如接受[2,3]时候相应下标区间就是[1,2];[3,10]的相应下标区间是[2,4];
 *  处理频率的时候,我们发现两个极端,也就是左右两个端点的频率不好处理。因为它们是不完全的频率
 *  也就是说有部分不在区间内。但是如果对于完全区间,也就是说左右端点下标值完全在所求区间内。
 *  比如上例的[2,3]不好处理。但是如果是[1,6],或是[1,10]就很好处理了,只要像RMQ一样询问区间最大值就可以了。
 *  方法二:RMQ. 
 *  我们可以转化一下问题。将左右端点分开来考虑。
 *  现在对于离散后的询问区间我们可以分成3个部分.左端点,中间完全区间,右端点。
 *  对于中间完全区间线段树或RMQ都能轻松搞定。只要特判一左右的比较一下就得最后解了。
 */
int build(int a, int b);
int query(int index, int a, int b);

const int N = 100010;

struct NODE
{
    int b, e;   //  区间[b, e]
    int l, r;   //  左右子节点下标
    int number; //  区间内的最大频率值
    int last;   //  以 data[e]结尾且与 data[e]相同的个数:data[e-last+1]...data[e]
} node[N * 2 + 1];

int len, data[N];

int main()
{
    int n;
    while (scanf("%d", &n), n)
    {
        int i, q, a, b;
        scanf("%d", &q);
        for (i = 0; i < n; i++)
        {
            scanf("%d", &data[i]);
        }
        len = 0;    //  下标
        build(0, n - 1);
        while (q--)
        {
            scanf("%d%d", &a, &b);
            printf("%d\n", query(0, a - 1, b - 1)); //  输出区间的最大频率值,而非data[]
        }
    }
    return 0;
}

int build(int a, int b) //  建立线段树
{
    int temp = len, mid = (a + b) / 2;
    node[temp].b = a, node[temp].e = b;
    len++;
    if (a == b)
    {
        node[temp].number = 1;
        node[temp].last = 1;
        return temp;
    }
    node[temp].l = build(a, mid);
    node[temp].r = build(mid + 1, b);
    int left_c = node[temp].l, right_c = node[temp].r, p, lcount = 0, rcount = 0, rec, max = 0;
    rec = data[mid];
    p = mid;
    while (p >= a && data[p] == rec)
    {
        p--, lcount++;
    }
    node[left_c].last = lcount;
    rec = data[mid + 1];
    p = mid + 1;
    while (p <= b && data[p] == rec)
    {
        p++, rcount++;
    }
    node[right_c].last = rcount;
    if (data[mid] == data[mid + 1])
    {
        max = lcount + rcount;
    }
    if (node[left_c].number > max)
    {
        max = node[left_c].number;
    }
    if (node[right_c].number > max)
    {
        max = node[right_c].number;
    }
    node[temp].number = max;
    return temp;
}

int query(int index, int a, int b)
{
    int begin = node[index].b;
    int end = node[index].e;
    int mid = (begin + end) / 2;
    if (a == begin && b == end)
    {
        return node[index].number;
    }
    if (a > mid)
    {
        return query(node[index].r, a, b);
    }
    if (b < mid + 1)
    {
        return query(node[index].l, a, b);
    }
    int temp1, temp2, max;
    if (node[index].l > 0)
    {
        temp1 = query(node[index].l, a, mid);
    }
    if (node[index].r > 0)
    {
        temp2 = query(node[index].r, mid + 1, b);
    }
    max = temp1 > temp2 ? temp1 : temp2;
    if (data[mid] != data[mid + 1])
    {
        return max;
    }
    temp1 = node[node[index].l].last > (mid - a + 1) ? (mid - a + 1) : node[node[index].l].last;
    temp2 = node[node[index].r].last > (b - mid) ? (b - mid) : node[node[index].r].last;
    if (max < temp1 + temp2)
    {
        max = temp1 + temp2;
    }
    return max;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Python中进行统计数据的区间分布,可以使用分布分析的方法。可以按照以下步骤进行: 1. 导入必要的库和数据:使用matplotlib.pyplot和pandas库导入数据,并查看数据类型和长度。 2. 计算区间间隔:根据数据的最大值和最小值之差,确定分布的基本间隔。可以将整个范围分成若干个区间。 3. 统计数据分布:遍历数据列表,将每个数据值归类到相应的区间中,并计算每个区间内数据值的个数。 4. 输出区间频率:将每个区间和对应的频率打印出来,频率可以通过每个区间内的数据数量除以总数据数量得到。 引用中给出了一个统计数据分布的函数,你可以根据需要进行修改和使用。它将数据加载到变量relation中,然后计算区间间隔和统计每个区间内的数据数量,并打印出来。 这样,你就可以利用Python进行统计数据的区间分布分析了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [python数据特征分析--分布分析](https://blog.csdn.net/qq_42169061/article/details/106068472)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [python 统计数据区间分布](https://blog.csdn.net/onlyforbest/article/details/108026007)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值