UVA11235:Frequent values(RMQ)
阿新 • • 發佈:2018-08-11
tdi onu 數列 查詢 name one ive 簡單 addition 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.
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 Specification
The input consists of several test cases. Each test case starts with a line containing two integers n
The last test case is followed by a line containing a single 0.
Output Specification
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
lrj藍皮書上的題,但也是做了好幾遍才做對...
主要是把端點處理好。
題目大意:
給一個非降序排列的整數數組a,你的任務是對於一系列詢問(i, j),回答ai,ai+1...aj中次數出現最多的值所出現的次數。
分析:
由於數列是非降序的,所以所有相等的數都會聚集在一起。這樣我們就可以把整個數組進行編碼。如-1,1,1,2,2,2,4就可以編碼成(-1,1),(1,2),(2,3),(4,1)表示(a,b)數組中的a連續出現了b次。
用num[i]表示原數組下表是i的數在編碼後的第num[i]段。left[i],right[i]表示第i段的左邊界和右邊界,用coun[i]表示第i段有conu[i]個相同的數。
這樣的話每次查詢(L, R)就只要計算(right[L]-L+1),(R-left[R]+1)和RMQ(num[L]+1, num[R]-1)這三個值的最大值就可以了。
其中,RMQ是對coun數組進行取件查詢的結果。
特殊的,如果L和R在同一個區間內的話,那麽結果就是(R-L+1)
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; const int M = 1e5 + 5; int cnt[M],num[M],lef[M],righ[M],d[M][20]; //數組d右區間不必開的過大 int n,q,sec; void RMQ_init(int* a) { int n = sec+1 ; for(int i = 0; i < n; i++) { d[i][0] = a[i]; } for(int j = 1; (1<<j) <= n; j++) for(int i = 0; i+(1<<j)-1 < n; i++) { d[i][j] = max(d[i][j-1],d[i+(1<<(j-1))][j-1]); } } int RMQ(int l, int r) { if(l > r) return 0; int k = 0; while((1<<(k+1)) <= r-l+1) k++; return max(d[l][k],d[r-(1<<k)+1][k]); //因為包括ta自身,所以+1 } int main() { while(~scanf("%d",&n) ,n) { scanf("%d",&q); int temp; //段數從0開始 for(int i = 0; i < n; i++) { int t; scanf("%d",&t); if(i==0){temp = t; num[i] = sec; cnt[sec]++; lef[sec] = 0; righ[sec] = -1;} //初始化段的端點為0 if(temp==t) {num[i] = sec; cnt[sec]++; righ[sec]++;} else{num[i]=++sec; cnt[sec]++; lef[sec]=righ[sec]=i; temp=t;} } RMQ_init(cnt); while(q--) { int L,R; scanf("%d%d",&L,&R); L--,R--; if(num[L] == num[R]) { printf("%d\n",R-L+1); } else { int ans = 0; if(num[L]+1 <= num[R]-1) //存在中間段 ans = RMQ(num[L]+1,num[R]-1); int ans1 = max(righ[num[L]]-L+1,R-lef[num[R]]+1); //端點 ans = max(ans,ans1); printf("%d\n",ans); } } memset(cnt,0,n+1); } return 0; }
做了好大一會別人家的簡單模板題0000ooo.
UVA11235:Frequent values(RMQ)