您的位置:首页 > 其它

ACM: 线段树 poj 3368

2016-05-19 23:24 495 查看
Frequent values
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的序列, 有m次访问一个区间中, 出现最多的元素的次数.

 

解题思路:

    
1. 多次访问某个区间的问题, 一般用线段树来做. 题目给一段已经按照升序的序列, 需要先离散化.

        线段树每个节点需要设置2个域,
num:计算在原序列中的位置, count: 当前val值得元素个数.

        离散化之后建立一棵线段树,
插入元素相应的统计在每个段中的最多的元素. 用样例如图:

        



    2.
显然, [0,3]区间的count = 4, [0,1]区间的count = 4, [2,3]区间的count = 3, ...
,以此类推

       这是线段树离散化的建立,
剩下的问题就是怎么查询:

       (1).其实问题可以简化为一个:
就是如果要查询原序列[5,10]时(从下标1开始), 怎么将图中(1)段

           计算出2个1.
想一想可以发现, 当用二分查找的时候, 查找到相应的段时, p->left ==
p->right

          
记录想要查找的原序列区间[l, r]的count = (r-l+1); 这样处理在一个段中的问题了. 剩下跟一

          
般线段树搜索一样了.

 

代码:

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

#define MAX 100005

struct Node

{

 int count, num;//count:相应val值个数, num: 原序列序号

 int val;

}p[MAX];

struct node

{

 int l, r;

 int count, num;

 int val;

}pt[MAX*2];

int n, m;

int A, B;

inline int max(int a, int b)

{

 return a > b ? a : b;

}

inline int min(int a, int b)

{

 return a < b ? a : b;

}

void buildTree(int l, int r, int pos)

{

 pt[pos].l = l, pt[pos].r = r;

 pt[pos].count = pt[pos].num = 0;

 pt[pos].val =
-(1<<30);

 if(l == r) return ;

 int mid = (l+r)/2;

 buildTree(l, mid, pos*2);

 buildTree(mid+1, r, pos*2+1);

}

void insert(Node &a, int index, int pos)

{

 if(a.count > pt[pos].count)

 {

  pt[pos].count = a.count;

  pt[pos].val = a.val;

 }

 if(pt[pos].l == pt[pos].r) return ;

 int mid = (pt[pos].l+pt[pos].r)/2;

 if(index <= mid)

  insert(a, index, pos*2);

 else

  insert(a, index,
pos*2+1);

}

void find(int l, int r, Node &a, int pos)

{

 int ll, rr;

 if(pt[pos].l == 0) ll = 1;

 else ll = p[ pt[pos].l-1 ].num+1;
//当前区间的第一个序号

 rr = p[ pt[pos].r ].num;

 if(l == ll &&
r == rr)

 {

  a.count = pt[pos].count;

  a.val = pt[pos].val;

  return ;

 }

 if(pt[pos].l == pt[pos].r)

 {

  a.count = r-l+1;

  a.val = pt[pos].val;

  return ;

 }

 Node lside, rside;

 lside.count = rside.count = 0;

 int mid = (pt[pos].l+pt[pos].r)/2;

 if(l <= p[mid].num)

  find(l, min(p[mid].num, r),
lside, pos*2);

 if(r > p[mid].num)

  find(max(p[mid].num+1, l), r,
rside, pos*2+1);

 if(lside.count >
rside.count)

 {

  a.count = lside.count;

  a.val = lside.val;

 }

 else

 {

  a.count = rside.count;

  a.val = rside.val;

 }

}

int main()

{

 int i, j, t;

// freopen("input.txt","r",stdin);

 while(scanf("%d",&n) !=
EOF)

 {

  if(n == 0) break;

  else
scanf("%d",&m);

  scanf("%d",&p[0].val);

  p[0].num = p[0].count =
1;

  j = 0;

  for(i = 1; i <
n; ++i)

  {

   scanf("%d",&t);

   if(t ==
p[j].val)

   {

    p[j].num++;

    p[j].count++;

   }

   else

   {

    j++;

    p[j].count
= 1;

    p[j].num
= p[j-1].num+1;

    p[j].val
= t;

   }

  }

  n = j;

  buildTree(0, n, 1);
//总共区间变成了0~n了

  for(i = 0; i <=
n; ++i)

   insert(p[i],
i, 1);

  for(i = 0; i
< m; ++i)

  {

   scanf("%d
%d",&A, &B);

   Node
temp;

   find(A, B,
temp, 1);

   printf("%d\n",
temp.count);

  }

 }

 return 0;

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: