poj 3386 RMQ+离散化

来源:互联网 发布:php环境集成包 编辑:程序博客网 时间:2024/05/20 21:19

题意:
给你一个大小为N的递增的区间A,接下来是Q条询问
对于每条询问,输出区间(i,j)之间相等的点最多有多少个。

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.

思路:将相等的点合并,得到一个新的集合B, 对于A里的每一个节点,使用Hash记录它在B中的位置,对于B中的每一个节点,记录它在A中的起始位置和结束位置
对于每一个询问(a,b),
A的第a个元素在B中位置为p1,第b个元素在B中位置为p2
如果p1==p2,那么答案就是p2-p1+1
如果p1!=p2
那么 计算A[a]和A[b]在区间(a,b)里出现的次数.
然后 计算 使用RMQ在B中计算区间(p1+1,p2-1)的最大值.(p2-p1>1)
最后三者最大值就是答案 。

参考:线段树+离散化

代码:

#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <map>#define MST(s,q) memset(s,q,sizeof(s))#define INF 0x3f3f3f3f#define MAXN 100005#define Lchild id<<1#define Rchild (id<<1)+1using namespace std;struct node{    int start, end;} Node[MAXN];int arr[MAXN], N, Q, Hash[MAXN], rmq[MAXN][20];void init(int n) {    for (int i = 1; i <= n; i++ ) {        rmq[i][0] = Node[i].end - Node[i].start + 1;    }    for (int j = 1; (1 << j) <= n; j++)        for (int i = 1; i + (1 << j) - 1 <= n; i++)            rmq[i][j] = max(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);}int RMQ(int i, int j) {    int k = (int)(log(j - i + 1) / log(2));    return max(rmq[i][k], rmq[j - (1 << k) + 1][k]);}int main() {    while (scanf("%d", &N) && N) {        scanf("%d", &Q);        int k = 0, pre = INF;        for (int i = 1; i <= N; i++) {  // 离散化,合并相等的点,Node[]为合并后的新集合            scanf("%d", &arr[i]);            if (arr[i] != pre) {                pre = arr[i];                Node[++k].start = i;                Node[k].end = i;            }            else Node[k].end = i;            Hash[i] = k;        }        init(k);        int a, b;        while (Q--) {            scanf("%d%d", &a, &b);            int  pos1 = Hash[a], pos2 = Hash[b];            if (pos1 == pos2)               //  如果 arr[a]==arr[b]                printf("%d\n", b - a + 1 );            else {                          //   arr[a]!=arr[b]                int n1 = Node[pos1].end - a + 1;                int n2 = 0;                int n3 = b - Node[pos2].start + 1;                if (pos2 - pos1 > 1)                //  区间(a,b) 里 ,除了arr[a]和arr[b] 还有其他 数                    n2 = RMQ(pos1 + 1, pos2 - 1);                printf("%d\n", max(max(n1, n2), n3) );            }        }    }}
0 0