poj 3368

题目:http://poj.org/problem?id=3368

题意:给定n个数,给出一段区间,问区间内相同数最多的有一个

思路:首先把给的数进行处理,给n个数重新编号,相同的数编号相同,用结构体记录相同数在原数组中的左右位置,用一个辅助数组记录原数据对应的新编号,询问的时候去看给的区间对应到新编号里面的位置

View Code
  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <math.h>
  5 #define N 100010
  6 #define _clr(a,val) (memset(a,val,sizeof(a)))
  7 
  8 using namespace std;
  9 
 10 int a[N],hash[N],mx[25][N];
 11 struct node
 12 {
 13     int l,r;
 14 }p[N];
 15 int n,q,len;
 16 void rmqinit()
 17 {
 18     int i,j;
 19     for (i = 1; (1 << i) <= len; ++i)
 20     {
 21         for (j = 0; (j + (1 << (i - 1))) <= len; ++j)
 22         {
 23             mx[i][j] = max(mx[i-1][j],mx[i-1][j + (1 << (i - 1))]);
 24         }
 25     }
 26 }
 27 int rmqmax(int s,int e)
 28 {
 29     int k = log(1.0*(e - s + 1))/log(2.0);
 30     return max(mx[k][s],mx[k][e - (1 << k) + 1]);
 31 }
 32 void change()  //预处理
 33 {
 34     int i;
 35     i = 1;
 36     len = 0;
 37     while(i <= n)
 38     {
 39         int tem = N;
 40         int ans = 0;
 41         if(tem != a[i])
 42         {
 43             int temp = i;
 44             p[len].l = i;
 45             tem = a[temp++];
 46             hash[i] = len;
 47             ans ++;
 48             while(tem == a[temp])
 49             {
 50                 hash[temp++] = len;
 51                 ans++;
 52             }
 53             mx[0][len] = ans;
 54             p[len].r = temp - 1;
 55             len++;
 56             i = temp;
 57         }
 58     }
 59 }
 60 void slove(int s,int e)
 61 {
 62     if (hash[s] == hash[e]) // 如果对应的新标号相同,则直接输出个数
 63     {
 64         printf("%d\n",e - s + 1);
 65     }
 66     else if (hash[s] + 1 == hash[e])  // 如果恰好横跨两个区间,那么计算个数多的
 67     {
 68         printf("%d\n",max(p[hash[s]].r - s + 1,e - p[hash[e]].l + 1));
 69     }
 70     else  // 否则就用rmq来计算区间最值
 71     {
 72            int max1 = p[hash[s]].r - s + 1;
 73            int max2 = e - p[hash[e]].l + 1;
 74            int max3 = rmqmax(hash[s] + 1,hash[e] - 1);
 75            printf("%d\n",max(max(max1,max2),max3));
 76     }
 77 }
 78 int main()
 79 {
 80     int i,s,e;
 81     //freopen("data.txt","r",stdin);
 82     while (scanf("%d",&n))
 83     {
 84         if (!n) break;
 85         _clr(p,0);
 86         scanf("%d",&q);
 87         for (i = 1; i <= n; ++i)
 88         {
 89             scanf("%d",&a[i]);
 90         }
 91         change();
 92         rmqinit();
 93         while (q--)
 94         {
 95             scanf("%d%d",&s,&e);
 96             slove(s,e);
 97         }
 98     }
 99     return 0;
100 }
posted @ 2012-07-31 11:41  AC_Girl  阅读(220)  评论(0编辑  收藏  举报