POJ 3368 Frequent values(线段树)

来源:互联网 发布:第一创业证券待遇 知乎 编辑:程序博客网 时间:2024/06/05 21:56

这一个题目是求一个区间内重复数字的最大次数。

这题有一个特点,数字是递增滴,相同的数字肯定是连续的。

将相同的数字看做一个部分,hash保存每个数字属于哪个部分。对所有的部分建一颗二叉树,保存此区间内最大的重复数字的个数。

 

查询的时候分3中情况

1 在同一个部分,直接 尾 - 头 + 1就是结果

2 只差一个部分,分开算,在各个部分里面重复多少次,比较一下

3 中间有很多个部分,那么可以先根据2计算出两头的,在通过二叉树查询最大的重复数字个数

#include <iostream>#include <algorithm>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <string>#include <vector>#include <set>#include <map>#include <queue>#include <stack>#include <climits>//形如INT_MAX一类的#define MAX 100050#define INF 0x7FFFFFFF#define REP(i,s,t) for(int i=(s);i<=(t);++i)#define ll long long#define mem(a,b) memset(a,b,sizeof(a))#define mp(a,b) make_pair(a,b)#define L(x) x<<1#define R(x) x<<1|1# define eps 1e-5//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂using namespace std;struct node {    int l,r,mid,value;} tree[4*MAX];struct point {    int st,end;} cnt[MAX];int data[MAX],vis[MAX],maxx;void up(int num) {    tree[num].value = max(tree[L(num)].value ,tree[R(num)].value);}void build(int l,int r,int num) {    tree[num].l = l;    tree[num].r = r;    tree[num].mid = (l+r) >> 1;    if(l == r) {        tree[num].value = cnt[l].end - cnt[l].st + 1;        return ;    }    build(l,tree[num].mid,L(num));    build(tree[num].mid+1,r,R(num));    up(num);}int query(int l,int r,int num) {    if(l <= tree[num].l && r >= tree[num].r) {        return tree[num].value;    }    if(r <= tree[num].mid) {        return query(l,r,L(num));    } else if( l > tree[num].mid) {        return query(l,r,R(num));    } else {        return max(query(tree[num].mid+1,r,R(num)),query(l,tree[num].mid,L(num)));    }}void test(int n) {    for(int i=1; i<=3*n; i++) {        printf("l:%d r:%d value:%d\n",tree[i].l,tree[i].r,tree[i].value);    }}int main()  {    int i,n,q,a,b;    while(scanf("%d",&n)) {        if(n == 0)            return 0;        scanf("%d",&q);        for(i=1; i<=n; i++) {            scanf("%d",&data[i]);        }        memset(vis,0,n);        int t = 1;        cnt[t].st = 1;        vis[1] = t;        if(n == 1) {            cnt[t].end = 1;        }        for(i=2; i<=n; i++) {            if(data[i] != data[i-1]) {                cnt[t].end = i-1;                t++;                cnt[t].st = i;                vis[i] = t;            } else {                vis[i] = t;            }        }        cnt[t].end = n;        vis[n] = t;        build(1,t,1);        //test(t);        for(i=1; i<=q; i++) {            scanf("%d%d",&a,&b);            if(vis[a] == vis[b]) {                printf("%d\n",b - a+1);                continue;            }            if(vis[b] - vis[a] == 1) {                printf("%d\n",max(cnt[vis[a]].end - a+1,b - cnt[vis[b]].st + 1));                continue;            }            int p = max(cnt[vis[a]].end - a+1,b - cnt[vis[b]].st + 1);            printf("%d\n",max(p,query(vis[a]+1,vis[b]-1,1)));        }    }    return 0;}


原创粉丝点击