zoukankan      html  css  js  c++  java
  • HUNNU Contest 区间最值

    区间求最值
    Time Limit: 3000ms, Special Time Limit:7500ms, Memory Limit:32768KB
    Total submit users: 68, Accepted users: 45
    Problem 11460 : No special judgement
    Problem description
      给定一个长度为N 的数组,有q个询问。每一个询问是求在数组的一段区间内那个元素的因子的个数最大。比方24的因子的个数就是8。 
    Input
      首先是一个整数t。表示有t组測试数据,每组測试数据的第一行是一个整数N(1<=N<=10^6),第二行有N个整数ai(1<=ai<=10^6,i=1,2,.....N)表示数组的元素。

    第三行有一个整数q(1<=q<=10^5),代表有q个询问,接下来每一行有两个整数。li,ri(li<=ri,li>=1,ri<=N).代表数组的一段区间,而且li+1>=li,ri+1>=ri

    Output
      对于每组数据的每一个询问都输出一个整数表示在这段区间里面元素因子个数的最大值。
    Sample Input
    1
    10
    2 3 5 6 9 11 12 36 39 44
    3
    2 6
    3 8
    3 9
    Sample Output
    4
    9
    9
    Problem Source

      HUNNU Contest 
    http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11460

    这题感觉非常巧妙,首先学到了怎么把给定范围因子数打表,然后 怎么减少时间复杂度。

    假设打表后每次直接在给定范围内比較出最大值是会超时的,可是我们能够把前一次比較出来的最大值下标赋值出来,下次查找的话。直接从这个下标開始。会节约非常多时间。

    #include <cstdio>
    #include <cstring>
    #define maxn 1000005
    int find[maxn];
    int num[maxn];
    int main()
    {
    	memset(find, 0, sizeof(find));//把 maxn范围内数的因子数打表
    	for (int i = 1; i < maxn; i++){
    		for (int j = i; j < maxn; j += i) //每次加i就等于j扩大一倍,两倍。三倍,,。。,
    			find[j]++;
    	}
    	int t;
    	scanf("%d", &t);
    	while (t--)
    	{
    		int n, q;
    		scanf("%d", &n);
    		for (int i = 1; i <= n; i++)
    		{
    			scanf("%d", &num[i]);
    			//intf("%d
    ",find[num[i]]);
    		}
    		scanf("%d", &q);
    		int a, b, ans = -1;
    		int aa, bb, sign;
    		scanf("%d%d", &a, &b);
    		aa = a, bb = b;
    		for (int i = a; i <= b; i++) //先比較出第一组的最大值 保存下标
    			if (ans < find[num[i]]){
    				ans = find[num[i]];
    				sign = i;
    			}
    
    		printf("%d
    ", ans);
    		--q;  //注意
    		while (q--)
    		{
    			scanf("%d%d", &a, &b); 
    			if (sign >= aa&&sign <= a){   //假设上一次的下标在aa和a之间。那仅仅能从a開始
    				ans = -1;
    				for (int i = a; i <= b; i++)
    				if (ans < find[num[i]]){
    					ans = find[num[i]];
    					sign = i;
    				}
    			}
    			else     //否则直接从bb開始,由于else的话 sign仅仅能是大于a。所以能够直接从bb開始。
    			{
    				for (int i = bb; i <= b; i++)
    				if (ans < find[num[i]]){
    					ans = find[num[i]];
    					sign = i;
    				}
    			}
    			aa = a, bb = b;
    			printf("%d
    ", ans);
    		}
    	}
    	return 0;
    }
    


    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    git命令无法自动补全(sles11.3)
    linux下安装svn出现configure: error: We require OpenSSL; try --with-openssl
    Linux系统下升级Python版本步骤(suse系统)
    git commit --amend
    关于device tree中的interrupts选项
    BufferedInputStream
    FileInputStream
    FileOutputStream
    泛型上下限
    泛型接口
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4616486.html
Copyright © 2011-2022 走看看