[uva11235]Frequent values(RMQ,ST,离散化)

题目链接:https://vjudge.net/problem/UVA-11235

题意:给一串不递减数字,q次询问,每次查询[l,r]内出现次数最多的数字出现的次数。

查询分两部分:一部分是[l,r]为同一个数的区间,另一部分则是在上下界处截取一部分的情况。

首先离散化,后用l[],r[],v[]分别记录每一段相同数字的左右区间和出现次数。v可以直接由r-l+1更新得到。

第一部分更新ret后,接下来的rmq分三部分:

第一部分查询左边界截取一部分的数字的当前长度,第二部分查询右边界的,第三部分查询删掉左右边界后中间完整的部分的最值。

ST表维护最值就好了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 typedef long long LL;
 5 const int maxn = 100100;
 6
 7 int n, m, q;
 8 int a[maxn];
 9 int h[maxn], hcnt;
10
11 int l[maxn], r[maxn], v[maxn];
12 int dp[maxn][33];
13
14 void st(int* b) {
15     for(int i = 1; i <= m; i++) dp[i][0] = b[i];
16     int k = int(log(n+1.0)/log(2.0));
17     for(int j = 1; j <= k; j++) {
18         for(int i = 1; i + (1 << j) - 1 <= m; i++) {
19             dp[i][j] = max(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
20         }
21     }
22 }
23
24 int query(int l, int r) {
25     int k = int(log(r-l+1.0)/log(2.0));
26     return max(dp[l][k], dp[r-(1<<k)+1][k]);
27 }
28
29 int id(int x) {
30     return lower_bound(h, h+hcnt, x) - h + 1;
31 }
32
33 int main() {
34     // freopen("in", "r", stdin);
35     while(~scanf("%d",&n) && n) {
36         scanf("%d", &q);
37         memset(l, 0, sizeof(l));
38         memset(r, 0, sizeof(r));
39         memset(v, 0, sizeof(v));
40         m = -1;
41         int pre = -1, ll = 1, rr, cnt = 0;
42         for(int i = 1; i <= n; i++) {
43             scanf("%d", &a[i]);
44             h[i-1] = a[i];
45         }
46         sort(h, h+n); hcnt = unique(h, h+n) - h;
47         for(int i = 1; i <= n; i++) a[i] = id(a[i]);
48         for(int i = 1; i <= n; i++) {
49             if(pre != a[i]) {
50                 l[++m] = ll, r[m] = i - 1;
51                 v[m] = r[m] - l[m] + 1;
52                 pre = a[i];
53                 ll = i;
54                 cnt = 1;
55             }
56             else rr++, cnt++;
57         }
58         l[++m] = ll, r[m] = n;
59         v[m] = r[m] - l[m] + 1;
60         st(v);
61         while(q--) {
62             scanf("%d %d", &ll, &rr);
63             if(a[ll] == a[rr]) {
64                 cout << rr - ll + 1 << endl;
65                 continue;
66             }
67             int ret = max(0, r[a[ll]]-ll+1);
68             ret = max(ret, rr-l[a[rr]]+1);
69             if(a[ll] + 1 <= a[rr] - 1) ret = max(ret, query(a[ll]+1, a[rr]-1));
70             cout << ret << endl;
71         }
72     }
73     return 0;
74 }
时间: 2024-11-19 19:08:59

[uva11235]Frequent values(RMQ,ST,离散化)的相关文章

POJ 3368 Frequent values RMQ ST算法/线段树

                                                     Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15229   Accepted: 5550 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In

Uva11235 Frequent values (RMQ)

///对于每个询问(l,r),分为两个部分,前半部分求与l之前相同的数的个数直到t,后半部分从t开始直接用RMQ求解最大值就行了. ///最后结果为max(前半部分,后半部分). # include <algorithm> # include <string.h> # include <math.h> # include <iostream> using namespace std; int f[100100];///前i个有多少个相同的数 int dp[1

uva 11235 - Frequent values(RMQ)

题目链接:uva 11235 - Frequent values 题目大意:给定一个非降序的整数数组,要求计算对于一些询问(i,j),回答ai,ai+1,-,aj中出现最多的数出现的次数. 解题思路:因为序列为非降序的,所以相同的数字肯定是靠在一起的,所以用o(n)的方法处理处每段相同数字的区间.然后对于每次询问: num[i]=num[j]:j?i+1 numi≠numj:max(RMQ(righti+1,reftj?1),max(righti?i+1,j?leftj+1)) #include

poj 3368 Frequent values(RMQ)

1 /************************************************************ 2 题目: Frequent values(poj 3368) 3 链接: http://poj.org/problem?id=3368 4 题意: 给出n个数和Q个询问(l,r),对于每个询问求出(l,r)之 5 间连续出现次数最多的次数 6 算法: RMQ 7 思路: 借助数组f[i].表示第i位前面有f[i]个相同的数.对于 8 每个区间(l,r).暴力求前面几个

【暑假】[实用数据结构]UVa11235 Frequent values

UVa 11235 Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 11241   Accepted: 4110 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In addition to that, you are given several qu

uva11235(Frequent values)(HDU1806)

题目地址:Frequent values 题目大意.解题思路:  见白皮书p198. 代码: 1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <algorithm> 5 #include <vector> 6 using namespace std; 7 const int M=100100; 8 int a[M]; 9 int val[M],cn

POJ 3368:Frequent values RMQ

Frequent values 题目链接: http://poj.org/problem?id=3368 题意: 给出一个非递减序列,求区间内最多的数字的数量 题解: 水题,dp[i][j]记录从 i 开始2^j个数中的出现最多的数,合并dp[i][j]和dp[i+(1<<j)][j]得到dp[i][1<<(j+1)]的时候,由于序列是连续的,只要多考虑一个i+(1<<j)-1(即dp[i][j]所能到达的最右端)上得数字在区间内出现的次数就好了. 代码 #includ

[POJ3368][UVA11235] Frequent values[ST表]

题意:给出一个不降序列,有多个询问,询问[l,r]中出现次数最多的数的出现次数 多组数据 对于序列-1 -1 1 1 1 1 3 10 10 10 可以这么理解<-1,2>, <1, 4>, <3,1>, <10,3> cnt[i]记录这个数字的出现次数,lef[i]记录左端点,righ[i]记录右端点,belong[i]代表第i个数字属于哪一块 把块和数量丢进st表 然后对于区间[l,r],答案就是 \(min(r, righ[l])-l+1\),\(r-

UVA-11235 Frequent values (RMQ)

题目大意:在一个长度为n的不降序列中,有m次询问,每次询问(i,j)表示在区间(i,j)中找出出现次数最多的元素的出现次数. 题目分析:因为序列有序,可以将序列分段,并且记录每段的元素个数.每一个元素所属的段num(i).每一个元素所属段的左端点l(i)及右端点r(i).那么对于每次询问: ans(i,j)=max(max(r(i)-i+1,j-l(j)+1),rmq(num(i)+1,num(j)-1)). ans(i,j)=r-j+1 (如果i与j属于同一段) 代码如下: # include