uva11235 Frequent values

思路:这个是RMQ变形,因为这个是一个non-decreasing order序列,所以同一个数是连续的,那么我们可以先处理下每个连续的数的左右边界,也就是l[i],r[i]的值,num[i]表示当前位置的数所属段的标号。对每种数进行编号,也就是每个段。建立Segment-Tree,再就是询问的时候,因为给的是原坐标,所以要转换成所属的段标号,如果是同一个段,那么直接坐标相减+1,否则就进行RMQ的询问,这里要注意两端的情况,看下面代码吧。

// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
// #define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define MEM(x,y) memset(x, y,sizeof x)
#define lson(x) ((x) << 1)
#define rson(x) ((x<<1)|1)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
int cnt[maxn], l[maxn], r[maxn], val[maxn], num[maxn];
int a[maxn];
int dp[maxn][30];
void RMQ_Init(int t){
	int n = t;
	for (int i = 0;i < n;i++)
		dp[i][0] = cnt[i];
	for (int j = 1;(1 << j) <= n;j++){
		for (int i = 0;i + (1 << j) - 1 < n;i++)
			dp[i][j] = max(dp[i][j-1],dp[i+(1 << (j-1))][j-1]);
	}
}
int RMQ(int L,int R){
	int k = 0;
	while((1 << (k + 1)) <= R - L + 1) k++;
	return max(dp[L][k],dp[R-(1<<k)+1][k]);
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int n,q;
	while(scanf("%d",&n) && n){
		scanf("%d",&q);
		for (int i = 0;i < n;i++)
			scanf("%d",&a[i]);
		MEM(cnt, 0);
		MEM(l, 0);
		MEM(r, 0);
		int t = 0, tmp = 1;
		for (int i = 1;i < n - 1;i++){//预处理
			if (a[i] != a[i - 1]){
				cnt[t] = tmp;
				r[t] = i - 1;//当前段的右值
				t++;//段的标号
				num[i] = t;//当前位置的数所属段的标号
				l[t] = i;//下个段的左值
				tmp = 1;//计数 
			}else {
				tmp++;
				num[i] = t;
			}
		}
		r[t] = n - 1;
		cnt[t] = tmp;
		num[n-1] = t;
		RMQ_Init(t);//建立线段树
		while(q--){
			int x,y;
			scanf("%d%d",&x,&y);
			x--,y--;
			int L = num[x], R = num[y];
			if (L == R){
				printf("%d\n",y-x+1);
				continue;
			}
			int Max = 0;
			Max = max(r[L]-x+1,y-l[R]+1);
			if (R -1 >= L+1)
				Max = max(Max,RMQ(L+1,R-1));
			printf("%d\n",Max);
		}
	}
	return 0;
}


你可能感兴趣的:(tree,segment)