您的位置:首页 > 产品设计 > UI/UE

hdu 1806 Frequent values 线段树

2015-12-22 18:48 323 查看
题目链接

给一个非递减数列, n个数, m个询问, 每个询问给出区间[L, R], 求这个区间里面出现次数最多的数的次数。

非递减数列, 这是最关键的一个条件...

需要保存一个区间最左边的数, 最右边的数, 最长前缀, 最长后缀, 和这个区间里面次数最多的数的次数。

一个区间出现最多的数的次数, 应该是左区间和右区间里面取一个最大值。 如果左区间最右边的数和右区间最左边的数相同, 还需要判断这个数左右区间加起来的数量是否大于最大值。

合并的时候需要判断左区间最右边的数和右区间最左边的数是否相同, 具体看代码。

#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 1e5+5;
int lnum[maxn<<2], rnum[maxn<<2], maxx[maxn<<2], pre_max[maxn<<2], suf_max[maxn<<2];
void pushUp(int rt, int m) {
maxx[rt] = max(maxx[rt<<1], maxx[rt<<1|1]);
lnum[rt] = lnum[rt<<1];
rnum[rt] = rnum[rt<<1|1];
suf_max[rt] = suf_max[rt<<1|1];
if(suf_max[rt] == (m>>1)&&lnum[rt<<1|1] == rnum[rt<<1])         //如果左区间最右边的数和右区间最左边的数相等
suf_max[rt] += suf_max[rt<<1];                              //并且左区间的后缀长度等于这段区间的长度
pre_max[rt] = pre_max[rt<<1];
if(pre_max[rt] == m-(m>>1) && rnum[rt<<1] == lnum[rt<<1|1])
pre_max[rt] += pre_max[rt<<1|1];
if(lnum[rt<<1|1] == rnum[rt<<1])
maxx[rt] = max(maxx[rt], pre_max[rt<<1|1]+suf_max[rt<<1]);
}
void build(int l, int r, int rt) {
if(l == r) {
scanf("%d", &lnum[rt]);
rnum[rt] = lnum[rt];
maxx[rt] = pre_max[rt] = suf_max[rt] = 1;
return ;
}
int m = l+r>>1;
build(lson);
build(rson);
pushUp(rt, r-l+1);
}
int query(int L, int R, int l, int r, int rt) {
if(L<=l&&R>=r) {
return maxx[rt];
}
int m = l+r>>1;
if(R<=m)
return query(L, R, lson);
if(L>m)
return query(L, R, rson);
int tmp1 = query(L, m, lson);
int tmp2 = query(m+1, R, rson);
int tmp3 = 0;
if(lnum[rt<<1|1] == rnum[rt<<1])
tmp3 = min(pre_max[rt<<1|1], R-m)+min(suf_max[rt<<1], m-L+1);
return max(tmp1, max(tmp2, tmp3));
}
int main()
{
int n, m;
while(cin>>n&&n) {
cin>>m;
build(1, n, 1);
while(m--) {
int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", query(x, y, 1, n, 1));
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: