题目: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 }