poj3368 frequent values (快状数组)
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 15763 | Accepted: 5732 |
Description
You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several queries consisting of indices i and j (1 ≤ i ≤ j ≤ n). For each query, determine the most frequent value among the integers ai , ... , aj.
Input
The input consists of several test cases. Each test case starts with a line containing two integers n and q (1 ≤ n, q ≤ 100000). The next line contains n integers a1 , ... , an (-100000
≤ ai ≤ 100000, for each i ∈ {1, ..., n}) separated by spaces. You can assume that for each i ∈ {1, ..., n-1}: ai ≤ ai+1. The following q lines contain one query each, consisting of two
integers i and j (1 ≤ i ≤ j ≤ n), which indicate the boundary indices for the
query.
The last test case is followed by a line containing a single 0.
Output
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
Sample Input
10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1 10 5 10 0
Sample Output
1 4 3
题意 : 给一个由n个元素组成的非严格上升的数组, q个询问(L,R), 输出位置在L~R的元素重复最多的个数
思路 :
由于是上升序列,所以重复的元素一定是在一起的,显然可以将原数组num
转化g[size],g[t]表示第t个重复元素出现的个数,size表示不同元素的个数。(O(N))
对于每个询问(L,R),首先求出num[L]和num[R]分别属于第几个重复的元素(即对应的g[]下标),方便缩小答案的范围。定义sum[]数组为g[]的前缀和,利用二分查找即可。
找出L,R对应的重复元素的在g[]的次序分别为l,r,考虑到首尾元素可能小于首尾元素重复的个数,就是L,R可能在重复元素的中间,则单独考虑。剩下的就是g[l+1]~g[r-1](注意l==r的情况答案就是R-L+1),也就是问题转化为求g[]在[l+1,r-1]的最大值以及首尾重复的数字个数k1,k2,他们之间的最大值即是答案。静态求数组区间最大值,线段树O(log size)或者平方分割O(sqrt(size))均可;
例如num[] = {-1,-1,1,1,1,1,3,10,10,10},n = 10;可转化为g[]={2,4,1,3},size = 4;sum[]={2,6,7,10};
对于询问(L=2,R=9),num[L]对应g[1],num[R]对应g[4],所以,l=1,r=4;k1 = 1,k2 = 2;而g[]在[2,3]最大为4;
故答案为4,k1,k2中最大值,即ans = 4;
附AC代码之前,向大神们求问此题另一解法是否可行,开始看错题目,没有看到是上升序列,就是{1,2,1,5,3,1,2,3}也是合法的,所以想到了离散化+线段树+莫队算法,先将数组离散化成[1,n]整数,对q个询问区间进行莫队算法,用线段树维护每个数出现的次数,并可logn返回数值区间出现的最多的次数。总觉得这个方法也是可行的,然而不会曼哈顿最小生成树,然后不知道写搓了还是卡了常数,悲伤的TLE了。
poj3368 AC代码,用的平方分割,没有线段树快。
Run ID | User | Problem | Result | Memory | Time | Language | Code Length | Submit Time |
15184614 | shnu_boy | 3368 | Accepted | 1084K | 1266MS | G++ | 2063B | 2016-02-21 17:29:37 |
//#include<bits/stdc++.h> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #include <map> #include <set> #include <vector> #include <queue> #include <utility> using namespace std; int const maxnum = 0x3f3f3f3f; int const maxn = 1e5 + 10; int num[maxn],sum[maxn]; int n,q; int block,b;//每个block数字个数容量 int s[maxn];//每个block的最大值 void init() { //memset(s,0,sizeof(s)); block = (int)ceil(sqrt((double)b)); for(int i = 1 ; i*block <= b ; i ++ ) { s[i] = -maxnum; for(int j = (i-1)*block+1 ; j <= block*i ; j ++ ) { s[i] = s[i] > num[j] ? s[i] : num[j]; } } } int find(int pos) { //pos对应的num序数 int high = b,low = 1,mid; while(low < high) { mid = ((high+low)>>1); if(sum[mid] < pos)low = mid+1; else if(sum[mid] == pos)high = low = mid; else high = mid; } return low; } int Ans(int L,int R) { int l=find(L),r=find(R); if(l == r){ return R-L+1; } int f1 = sum[l]-L+1,f2 = R-sum[r-1]; l++;r--; int ans = f1 > f2 ? f1 : f2; if(r-l <= block) { for(int t = l ; t <= r ; t ++ ) { if(num[t] > ans) ans = num[t]; } } else { f1 = f2 = 0; for(int t = l ; t <= (l-1)/block*block+block ; t ++ ) { if(num[t] > f1) f1 = num[t]; } for(int t = r ; t >= (r-1)/block*block+1 ; t -- ) { if(num[t] > f2) f2 = num[t]; } if(f2 > f1)f1 = f2; if(f1 > ans)ans = f1; for(int t = (l-1)/block+2; t <= (r-1)/block ; t ++ ) { if(ans < s[t]) ans = s[t]; } } return ans; } int main() { while(cin >> n && n) { cin >> q; b = 0;//block的数量 int k = maxnum;//扫描数字的前一个数字 for(int t = 1 ; t <= n ; t ++ ) { int g;//扫描的数字 scanf("%d",&g); if( g - k ) { b ++; num[b] = 1; k = g; } else { num[b] ++; } } for(int t = 1 ; t <= b ; t ++ ) { sum[t] = sum[t-1] + num[t]; } init(); for(int t = 1 ; t <= q ; t ++ ) { int L,R; scanf("%d%d",&L,&R); printf("%d\n",Ans(L,R)); } } return 0; }
- 点赞
- 收藏
- 分享
- 文章举报
- 关于MOSQUETTO配置文件mosquetto.conf的配置
- Grails Quick Start
- iOS开发 粗解UIDynamicAnimator
- Fluent NHibernate的配置
- C# 浅谈ThreadPool -- 上篇(Enqueue)
- @RequestMa'pping注解 value的值
- element-ui 表格表头禁用全选功能
- XMLHttpRequest Level 2 使用指南
- XMLHttpRequests规范文档
- HBuilder的常用快捷键
- intelliJ idea自动生成UID
- 连接数据库提示: 'Client does not support authentication protocol requested by server
- JSON 用Iterator 遍历key 和value
- 【Uinty】物理基础
- elementUI table表头错位问题
- Document is missing mandatory uniqueKey field: id解决方案
- 灵活实用require.js,让JS加载速度更流畅
- UGUI 5.0 一些笔记
- uicollectionview 不调用cellForItemAtIndexPath
- UIViewController