【蓝桥备赛】重复的数——莫队(Java/Cpp版)

文章讲述了在蓝桥杯C++比赛中遇到的关于区间范围内查询重复数的问题,作者使用了莫队的思想对查询进行排序并优化区间调整,但提到Java代码在某些情况下运行不稳定。寻求更稳定的Java或C++代码实现以提高性能。
摘要由CSDN通过智能技术生成

题目链接

重复的数
题目来源:第十三届蓝桥杯 C++ C 组省赛 J 题——重复的数

个人思路

主要思想——莫队,该思想参考学习地址 普通莫队算法

对于若干区间范围内的询问,可以通过其他区间的情况调整范围来得到答案。为了能够最小化区间范围的修改次数,我们需要将所有询问进行排序,排序规则是按照l 所在块的编号为第一关键字,r 为第二关键字从小到大排序。

参考代码

该死的Java,不懂在发什么电,同样的代码最后一个样例有时候能过,有时候会超时,波动超过1000ms就会超时。如果有哪位Java大佬发现了能够稳定通过的代码,记得评论区踢我一下!!

Java运行结果图

在这里插入图片描述

Java-1

import java.io.*;
import java.util.Arrays;

public class Main {
    static class Query implements Comparable<Query> {
        public int id, l, r, k;

        @Override
        public int compareTo(Query other) {
            if (this.l / maxn != other.l / maxn)
                return Integer.compare(this.l, other.l);
            return ((this.l / maxn) & 1) == 1 ? Integer.compare(this.r, other.r) : Integer.compare(other.r, this.r);
        }
    }

    static final int N = 100003;
    static int n, m, maxn;
    static int[] arr = new int[N];
    static int[] sum = new int[N];
    static int[] cnt = new int[N];
    static int[] ans = new int[N];
    static Query[] q = new Query[N];

    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }

    public static void main(String[] args) throws IOException {
        n = nextInt();
        for (int i = 1; i <= n; ++i) {
            arr[i] = nextInt();
        }
        maxn = (int) Math.sqrt(n);
        m = nextInt();
        for (int i = 0; i < m; ++i) {
            q[i] = new Query();
            q[i].id = i;
            q[i].l = nextInt();
            q[i].r = nextInt();
            q[i].k = nextInt();
        }
        Arrays.sort(q, 0, m);
        int l = 1, r = 0;
        for (int i = 0; i < m; ++i) {
            while (l > q[i].l) {
                --l;
                sum[cnt[arr[l]]]--;
                cnt[arr[l]]++;
                sum[cnt[arr[l]]]++;
            }
            while (r < q[i].r) {
                ++r;
                sum[cnt[arr[r]]]--;
                cnt[arr[r]]++;
                sum[cnt[arr[r]]]++;
            }
            while (l < q[i].l) {
                sum[cnt[arr[l]]]--;
                cnt[arr[l]]--;
                sum[cnt[arr[l]]]++;
                l++;
            }
            while (r > q[i].r) {
                sum[cnt[arr[r]]]--;
                cnt[arr[r]]--;
                sum[cnt[arr[r]]]++;
                r--;
            }
            ans[q[i].id] = sum[q[i].k];
        }
        for (int i = 0; i < m; ++i) {
            System.out.println(ans[i]);
        }
    }
}

Java-2

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.Comparator;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }
    static int n, m;
    // res[i] 出现次数为 i 的个数
    // cnt[i] 数字 i 出现的次数
    static int[] arr, res, cnt, ans;
    static int maxn;
    static class Query {
        public int l, r, k, id;
    }
    static Query[] queries;
    static void increase(int index) {
        res[cnt[arr[index]]]--;
        cnt[arr[index]]++;
        res[cnt[arr[index]]]++;
    }
    static void decrease(int index) {
        res[cnt[arr[index]]]--;
        cnt[arr[index]]--;
        res[cnt[arr[index]]]++;
    }
    public static void main(String[] args) throws IOException {
        res = new int[100003];
        cnt = new int[100003];
        n = nextInt();
        arr = new int[n + 1];
        maxn = (int) Math.sqrt(n);
        for(int i = 1; i <= n; ++i) {
            arr[i] = nextInt();
        }
        m = nextInt();
        queries = new Query[m];
        ans = new int[m];
        for(int i = 0; i < m; ++i) {
            queries[i] = new Query();
            queries[i].id = i;
            queries[i].l = nextInt();
            queries[i].r = nextInt();
            queries[i].k = nextInt();
        }
        Arrays.sort(queries, new Comparator<Query>() {
            @Override
            public int compare(Query o1, Query o2) {
                if(o1.l / maxn != o2.l / maxn) {
                    return o1.l / maxn - o2.l / maxn;
                }
                return o1.r - o2.r;
            }
        });
        int le = 1, ri = 0;
        for(int i = 0; i < m; ++i) {
            while (le > queries[i].l) {
//                increase(--le);
                --le;
                res[cnt[arr[le]]]--;
                cnt[arr[le]]++;
                res[cnt[arr[le]]]++;
            }
            while(ri < queries[i].r) {
//                increase(++ri);
                ++ri;
                res[cnt[arr[ri]]]--;
                cnt[arr[ri]]++;
                res[cnt[arr[ri]]]++;
            }
            while(le < queries[i].l) {
//                decrease(le++);

                res[cnt[arr[le]]]--;
                cnt[arr[le]]--;
                res[cnt[arr[le]]]++;
                le++;
            }
            while (ri > queries[i].r) {
//                decrease(ri--);

                res[cnt[arr[ri]]]--;
                cnt[arr[ri]]--;
                res[cnt[arr[ri]]]++;
                ri--;
            }
            ans[queries[i].id] = res[queries[i].k];
        }
        for(int i = 0; i < m; ++i)
            System.out.println(ans[i]);
    }
}

Java-3

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.Comparator;

public class Main {
    static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }
    static int n, m;
    // res[i] 出现次数为 i 的个数
    // cnt[i] 数字 i 出现的次数
    static int[] arr, res, cnt, ans;
    static int maxn;
    static class Query {
        public int l, r, k, id;
    }
    static Query[] queries;
    static void increase(int index) {
        res[cnt[arr[index]]]--;
        cnt[arr[index]]++;
        res[cnt[arr[index]]]++;
    }
    static void decrease(int index) {
        res[cnt[arr[index]]]--;
        cnt[arr[index]]--;
        res[cnt[arr[index]]]++;
    }
    public static void main(String[] args) throws IOException {
        res = new int[100003];
        cnt = new int[100003];
        n = nextInt();
        arr = new int[n + 1];
        maxn = (int) Math.sqrt(n);
        for(int i = 1; i <= n; ++i) {
            arr[i] = nextInt();
        }
        m = nextInt();
        queries = new Query[m];
        ans = new int[m];
        for(int i = 0; i < m; ++i) {
            queries[i] = new Query();
            queries[i].id = i;
            
            queries[i].l = nextInt();
            queries[i].r = nextInt();
            queries[i].k = nextInt();
            
        }
        Arrays.sort(queries, new Comparator<Query>() {
            @Override
            public int compare(Query o1, Query o2) {
                if(o1.l / maxn != o2.l / maxn) {
                    return o1.l / maxn - o2.l / maxn;
                }
                return o1.r - o2.r;
            }
        });
        int le = 1, ri = 0;
        for(int i = 0; i < m; ++i) {
            while (le > queries[i].l) {
                increase(--le);
            }
            while(ri < queries[i].r) {
                increase(++ri);
            }
            while(le < queries[i].l) {
                decrease(le++);
            }
            while (ri > queries[i].r) {
                decrease(ri--);
            }
            ans[queries[i].id] = res[queries[i].k];
        }
        for(int i = 0; i < m; ++i)
            System.out.println(ans[i]);
    }
}

Cpp

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 3;
#define endl "\n"

class Query
{
public:
    int id, l, r, k;
} q[N];

int n, m, arr[N], sum[N], cnt[N], maxn, ans[N];

int cmp(Query q1, Query q2)
{
    if (q1.l / maxn != q2.l / maxn)
        return q1.l < q2.l;
    return (q1.l / maxn) & 1 ? q1.r < q2.r : q1.r > q2.r;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; ++i)
    {
        cin >> arr[i];
    }
    maxn = sqrt(n);
    cin >> m;
    for (int i = 0; i < m; ++i)
    {
        q[i].id = i;
        cin >> q[i].l >> q[i].r >> q[i].k;
    }
    sort(q, q + m, cmp);
    int l = 1, r = 0;
    for (int i = 0; i < m; ++i)
    {
        while (l > q[i].l)
        {
            --l;
            sum[cnt[arr[l]]]--;
            cnt[arr[l]]++;
            sum[cnt[arr[l]]]++;
        }
        while (r < q[i].r)
        {
            ++r;
            sum[cnt[arr[r]]]--;
            cnt[arr[r]]++;
            sum[cnt[arr[r]]]++;
        }
        while (l < q[i].l)
        {
            //                decrease(le++);

            sum[cnt[arr[l]]]--;
            cnt[arr[l]]--;
            sum[cnt[arr[l]]]++;
            l++;
        }
        while (r > q[i].r)
        {
            sum[cnt[arr[r]]]--;
            cnt[arr[r]]--;
            sum[cnt[arr[r]]]++;
            r--;
        }
        ans[q[i].id] = sum[q[i].k];
    }
    for (int i = 0; i < m; ++i)
        cout << ans[i] << endl;
    return 0;
}
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值