zoukankan      html  css  js  c++  java
  • POJ-3368 Frequent values(RMQ)

    题意:你被给予了一个非单调递减的n个数字的序列a1, a2, ..., an。除此之外,你被给予了q个询问,每个询问由i, j(1 <= i <= j <= n)。求这个区间内出现最多的数的次数。

    分析:这是一个非单调递减的序列,比如样例中的-1 -1 1 1 1 1 3 10 10 10,我们可以得到每个连续相等区间的数字次数为2 4 1 3,这个序列可以用RMQ维护。但是询问中的[L, R]不一定是正好在某个连续区间的边界,因此,我们可以求出左右两个多出来的区间部分的数的次数,中间连续的区间再用RMQ查询。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    const int N = 100005;
    const int M = 18;
    int f[N], val[N], pos[N];
    int l[N], r[N];
    int g[N], idx;
    int dp[N][M];
    int n, q;
    
    void init()
    {
    	for(int j = 0; j < M; ++j)
    		for (int i = 1; i + (1 << j) - 1 <= idx; ++i)
    		{
    			if (!j) dp[i][j] = g[i];
    			else dp[i][j] = max(dp[i][j - 1], dp[i + (1 << j - 1)][j - 1]);
    		}
    }
    
    int query(int L, int R)
    {
    	int p = pos[L], q = pos[R];
    	if (p == q)
    	{
    		return R - L + 1;
    	}
    	else
    	{
    		int k1 = r[p] - L + 1;
    		int k2 = R - l[q] + 1;
    		++p, --q;
    		if (p <= q)
    		{
    			int len = q - p + 1;
    			int t = log((double)len) / log((double)2);
    			return max(max(k1, k2), max(dp[p][t], dp[q - (1 << t) + 1][t]));
    		}
    		else
    		{
    			return max(k1, k2);
    		}
    	}
    	
    }
    
    void clear()
    {
    	idx = 0;
    	memset(dp, 0, sizeof dp);
    }
    
    int main()
    {
    	while (scanf("%d", &n) != EOF)
    	{
    		if (n == 0) break;
    		scanf("%d", &q);
    		for (int i = 1; i <= n; ++i) scanf("%d", &val[i]);
    
    		int i;
    		for (i = 1; i <= n; ++i)
    		{
    			if (val[i] == val[i - 1] && i - 1 != 0)
    			{
    				f[i] = f[i - 1] + 1;
    			}
    			else
    			{
    				l[idx] = i - f[i - 1], r[idx] = i - 1;
    				g[idx] = f[i - 1];
    				f[i] = 1;
    				++idx;
    			}
    			pos[i] = idx;
    		}
    		l[idx] = i - f[i - 1], r[idx] = i - 1;
    		g[idx] = f[i - 1];
    
    		init();
    
    		int l, r;
    		while (q--)
    		{
    			scanf("%d%d", &l, &r);
    			printf("%d
    ", query(l, r));
    		}
    		clear();
    	}
    
    
    	return 0;
    }
    
  • 相关阅读:
    从请假日期列表中取得请假起止日期
    存储过程编写经验和优化措施
    安装IE8不能调试VS2003的解决办法
    javascript驗證若干DropDownList是否有選择
    欢迎光临C/S框架网 www.csframework.com
    C#开发框架钢铁贸易进销存系统演示视频
    基于.Net C/S结构系统开发框架V2.2正式发布!
    C#.NET Winform+WebService开发框架完整版本
    C#.Net C/S快速开发框架V2.2版本介绍
    专注C# .Net C/S结构系统开发框架,C/S框架网
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13355043.html
Copyright © 2011-2022 走看看