1 条题解

  • 0
    @ 2024-6-12 19:07:09

    题意:有一个长度为 n 的序列 A,给出 q 组询问,每次询问 A 在区间 [l,r] 内有几个 x。总共 T 组数据。

    题意还是比较简明易懂的。n≤10510^5的数据范围,首先排除 O(n2n^2) 的暴力。

    不妨把“在区间[l,r]内有几个 x”转化为“x 在区间 [l,r] 出现了几次”,那么可以考虑对于每一种 x 的值都开一个数组记录每个 x 出现的位置。每次询问时,分别二分出区间里最靠左的 x 编号和最靠右的 x 编号,两数相减再加一就是答案了。

    但是 Ai≤10910^9,n≤10510^5,开一个 10910^9×10510^5大小的数组显然是不科学的,那就把 Ai离散化一下,这样 Ai≤10510^5 了,可是开一个 10510^5×10510^5的数组依然吃不消。那么就开 10510^5vector ~

    #include<bits/stdc++.h>
    #define N 100005
    using namespace std;
    
    int T;
    int n,m,q,a[N],b[N];
    vector<int> c[N];
    //a:原数组  b:离散化的a数组  c:存每个b[i]出现的位置
    
    int main()
    {
    	scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d",&n);
    		for(int i = 1;i <= n;i++)scanf("%d",&a[i]),b[i] = a[i],c[i].clear();
    		//多测数据要清零。
    		sort(b+1,b+1+n);
    		m = unique(b+1,b+1+n)-b-1;
    		for(int i = 1;i <= n;i++)a[i] = lower_bound(b+1,b+m+1,a[i])-b,c[a[i]].push_back(i);
    		scanf("%d",&q);
    		while(q--)
    		{
    			int l,r,x,y;
    			scanf("%d%d%d",&l,&r,&x);
    			y = lower_bound(b+1,b+1+m,x)-b;
    			if(b[y] != x)printf("0\n");
    			else printf("%d\n",upper_bound(c[y].begin(),c[y].end(),r)-lower_bound(c[y].begin(),c[y].end(),l));
    			//这里输出答案其实有一个抵消,就是用“第一个大于r”的位置去减掉“第一个大于等于l”的位置
    		}
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    645
    时间
    1000ms
    内存
    128MiB
    难度
    7
    标签
    递交数
    18
    已通过
    9
    上传者