标签:printf enc ber 初始化 star seq ted nsis print
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.
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.
For each query, print one line with one integer: The number of occurrences of the most frequent value within the given range.
10 3 -1 -1 1 1 1 1 3 10 10 10 2 3 1 10 5 10 0
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.
标签:printf enc ber 初始化 star seq ted nsis print
原文地址:https://www.cnblogs.com/lwsh123k/p/9460002.html