牛客网多校1 Different Integers(莫队或树状数组)

本文介绍了一种使用莫队算法和树状数组进行区间查询优化的方法,适用于处理大量区间查询问题,尤其是在数据规模较大时能够显著提升效率。

给你一个数组, 长度n<=1e5, q次询问(l, r), 输出区间[1, l], [r, n]中不同数字的个数, q<=1e5

莫队 简单粗暴:

#include <bits/stdc++.h>
 
using namespace std;
const int maxn=1e5+10;
struct node{
    int l,r,id;
}s[maxn];
int block[maxn],t,n,m;
int a[maxn],c[maxn],ans[maxn];
bool cmp(const node&a,const node &b)
{
    if(block[a.l]==block[b.l]) return a.r<b.r;
    return a.l<b.l;
}
int main()
{
    //cout << "Hello world!" << endl;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        int t=sqrt(n);
        for(int i=1;i<=n;i++)
            block[i]=(i-1)/t;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].l,&s[i].r);
            s[i].id=i;
        }
        int l=0,r=n+1;
        for(int i=1;i<=n;i++)
            c[i]=0;
        sort(s+1,s+m+1,cmp);
        int num=0;
        for(int i=1;i<=m;i++)
        {
            while(l<s[i].l)
            {
                l++;
                c[a[l]]++;
                if(c[a[l]]==1)
                    num++;
            }
            while(l>s[i].l)
            {
                c[a[l]]--;
                if(c[a[l]]==0)
                    num--;
                l--;
            }
            while(r>s[i].r)
            {
                r--;
                c[a[r]]++;
                if(c[a[r]]==1)
                    num++;
            }
            while(r<s[i].r)
            {
                c[a[r]]--;
                if(c[a[r]]==0)
                    num--;
                r++;
            }
 
            ans[s[i].id]=num;
        }
        for(int i=1;i<=m;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}

树状数组:

#include <bits/stdc++.h>

using namespace std;
const int maxn=1e5+10;
struct node{
    int l,r,id;
}s[maxn];
bool cmp(const node&a,const node&b)//右端点大的优先
{
    if(a.r==b.r) return a.l<b.l;
    return a.r>b.r;
}
int n,m,a[maxn],first[maxn],vis[maxn];
int sum[maxn];
int lowbit(int x){return x&-x;}
void update(int pos,int val)
{
    while(pos<=n)
    {
        sum[pos]+=val;
        pos+=lowbit(pos);
    }
}
int query(int pos)
{
    int ans=0;
    while(pos>0)
    {
        ans+=sum[pos];
        pos-=lowbit(pos);
    }
    return ans;
}
int pre[maxn],ans[maxn];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(first,0,sizeof first);
        int res=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(!first[a[i]])
            {
                first[a[i]]=i;
                res++;
            }
            pre[i]=res;///记下i位置前面不同数的个数
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].l,&s[i].r);
            s[i].id=i;
        }
        sort(s+1,s+m+1,cmp);
        memset(sum,0,sizeof sum);
        memset(vis,0,sizeof vis);
        int l=0,r=n+1;
        res=0;///从后往前遇到的不同数的个数
        for(int i=1;i<=m;i++)
        {
            while(r>s[i].r)
            {
                r--;
                if(!vis[a[r]])
                {
                    res++;
                    vis[a[r]]=1;
                    update(first[a[r]],1);
                }
            }
            ans[s[i].id]=pre[s[i].l]+res-query(s[i].l);//s[i].l以前不同数的个数+res-前后重复出现的数量
        }
        for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    }

    return 0;
}

 

<think>好的,我现在需要在Java中创建一个所有元素都初始化为1的数组。让我仔细想想怎么做。 首先,我回忆一下Java数组的初始化方法。对于基本类型的数组,比如int数组,通常在声明时指定大小,然后元素会被自动初始化为默认值,比如int的默认值是0。所以如果我直接创建一个int数组,元素都是0,但我要的是1,所以不能直接用默认初始化。 那有没有办法在创建数组的时候直接赋值为1呢?我记得可以使用循环来遍历数组,逐个赋值。比如: int[] arr = new int[5]; for (int i = 0; i < arr.length; i++) { arr[i] = 1; } 这种方法应该是可行的。但用户可能想要更简洁的方法,不需要显式写循环。 接下来,我想到Java 8以后的Arrays.fill()方法。这个方法可以填充整个数组为指定的值。比如: int[] arr = new int[5]; Arrays.fill(arr, 1); 这样只需要两行代码,而且比较简洁。不过需要导入java.util.Arrays类。 另外,有没有可能在声明数组的时候就初始化所有元素为1呢?比如使用数组初始化语法: int[] arr = {1, 1, 1, 1, 1}; 但这种方法只适用于数组长度较小且已知的情况,如果数组很大,比如100个元素,手动写每个1会很麻烦,不可行。 对于维数组的情况,比如二维数组,可能需要嵌套循环次使用Arrays.fill。例如二维数组: int[][] matrix = new int[3][3]; for (int[] row : matrix) { Arrays.fill(row, 1); } 这样每个子数组都会被填充为1。 不过用户的问题可能主要针对一维数组。我需要确认是否有其他方法,比如使用Stream API。Java 8的流可以生成数组,例如: int[] arr = IntStream.generate(() -> 1).limit(5).toArray(); 这样生成一个长度为5,全是1的数组。这种方法对于较大的数组可能更高效,者更符合函数式编程的风格。 但需要注意的是,这种方式对于非常大的数组可能会有性能上的考虑,不过一般情况下应该没问题。 另外,用户提到的无效初始化方法,比如int[] integers[] = new int[4][5]; 这样的写法虽然有效,但不符合推荐的命名规范,容易引起混淆,所以应该避免。 总结一下,主要方法有: 1. 使用循环逐个赋值。 2. 使用Arrays.fill方法。 3. 对于小数组,手动初始化。 4. 使用Java 8的流生成。 根据用户的需求,可能需要选择最简洁高效的方法。Arrays.fill者流的方法都比较合适。同时需要提醒用户,不能直接通过new int[n]来初始化为1,因为默认是0。 此外,需要注意数组是固定长度的,初始化后长度不能改变,所以创建时需要确定大小。 最后,可能用户没有考虑到维数组的情况,者是否有其他特殊情况,比如包装类型数组,但如果是int数组的话,上述方法适用。</think>在Java中创建所有元素初始化为1的数组可以通过以下方法实现: ### 方法1:循环赋值(基础方法) ```java int[] arr = new int[5]; for (int i = 0; i < arr.length; i++) { arr[i] = 1; } ``` 此方法直接通过循环为每个元素赋值为1,适用于所有Java版本。 ### 方法2:使用`Arrays.fill()`(简洁高效) ```java import java.util.Arrays; int[] arr = new int[5]; Arrays.fill(arr, 1); ``` 该方法通过工具类`Arrays`的静态方法快速填充数组,代码简洁且可读性高[^1]。 ### 方法3:Java 8 Stream API(函数式编程) ```java import java.util.stream.IntStream; int[] arr = IntStream.generate(() -> 1).limit(5).toArray(); ``` 通过流生成固定长度的数组,适合需要动态生成与其他流操作结合的场景。 ### 维数组初始化 对于二维数组: ```java int[][] matrix = new int[3][3]; for (int[] row : matrix) { Arrays.fill(row, 1); } ``` 通过嵌套循环`Arrays.fill()`逐行填充。 ### 注意事项 - **无效初始化示例**:避免类似`int integers[][] = new int[5][];`的声明方式,这种混合写法易引发歧义。 - **默认值问题**:直接使用`new int[n]`会初始化为0,需额外操作改为1
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值