POJ 3368.Frequent values

2015-06-10

问题简述:

  输入一个非递减的数组,输出其中下标 i 到 j 中最大连续元素的个数。

  原题链接:http://poj.org/problem?id=3368

解题思路:

  由于数组长度和查询次数过大,使用遍历算法暴力求解必然导致 TLE,所以我们要另想方法。这里可以使用 RMQ问题中的ST算法或线段树 来优化问题解决的时间复杂度。

  方法一:ST算法,即 Sparse Table 算法。它的时间复杂度为<O(nlogn), O(1)>,即预处理为 O(nlogn),而查询仅需O(1)的时间。

      本文提供有关该算法的讲稿,链接: http://pan.baidu.com/s/1hqCg17I 密码: d3m3。

  方法二:线段树。线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。本题使用线段树存储区间最大值,使得查询时间复杂度降为 O(logn)。

  具体操作:使用一个数组 cnt 记录每一个数依次出现的次数,然后使用上述两个算法对这个数组进行操作,使利于查询。为了便于查找原数组下标,还要建立一个数据结构保存  cnt 对应的数的最小下标和最大下标以及 cnt 的下标。

源代码:

ST算法:

 1 /*

 2 OJ: POJ

 3 ID: 3013216109

 4 TASK: 3368.Frequent values

 5 LANG: C++

 6 NOTE: RMQ(ST算法)

 7 */

 8 #include <cstdio>

 9 #include <algorithm>

10 #include <cstring>

11 #include <cmath>

12 using namespace std;

13 

14 const int MAX=100005;

15 int a[MAX],dp[MAX][18];

16 int cnt[MAX];

17 

18 struct trip {

19     int s,e;

20     int num;

21 }wap[MAX];

22 

23 int main()

24 {

25     int n,q,x,y,i,j;

26     while(scanf("%d",&n),n) {

27         scanf("%d",&q);

28         memset(wap,0,sizeof(wap));

29         memset(cnt,0,sizeof(cnt));

30         int k=1;

31         scanf("%d",&a[1]);

32         wap[k].s=1;

33         for(i=2;i<=n;i++) {

34             scanf("%d",&a[i]);

35             if(a[i]==a[i-1]) {

36                 cnt[k]++;

37                 //wap[k].e=i;

38                 wap[i].s=wap[i-1].s;

39             }

40             else {

41                 cnt[k]++;

42                 wap[i].e=i-1;

43                 k++;

44                 wap[i].s=i;

45             }

46         }

47         wap[n+1].e=n;

48         cnt[k]++;

49         for(i=1,j=1;i<=n;) {

50             for(int f=i;f<i+cnt[j];f++)

51                 wap[f].num=j;

52             for(int f=i+1;f<i+cnt[j];f++)

53                 wap[f].s=wap[f-1].s;

54             for(int f=i+cnt[j]-1;f>=i;f--)

55                 wap[f].e=wap[f+1].e;

56             i+=cnt[j];j++;

57         }

58 

59         int f;

60         for(f=17;f>=0;f--)

61             if((1<<f)<=k)

62                 break;

63         f++;

64         int p=floor(log((double)(n+1))/log(2.0));

65         for(i=1;i<=k;i++)

66             dp[i][0]=cnt[i];

67         for(j=1;j<=p;j++)

68             for(i=1;i+(1<<j)-1<=k;i++)

69                 dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);

70 

71         while(q--) {

72             scanf("%d %d",&x,&y);

73             int i,st,rt,ans;

74             st=wap[x].num;

75             rt=wap[y].num;

76             if((rt-st)==0)

77                 ans=y-x+1;

78             else if((rt-st)==1)

79                 ans=max(wap[x].e-x+1,y-wap[y].s+1);

80             else {

81                 int p=floor((log((double)(rt-st-1))/log(2.0)));

82                 ans=max(dp[st+1][p],dp[rt-(1<<p)][p]);

83                 ans=max(wap[x].e-x+1,ans);

84                 ans=max(ans,y-wap[y].s+1);

85             }

86             printf("%d\n",ans);

87         }

88     }

89     return 0;

90 }

线段树:

  1 /*

  2 OJ: POJ

  3 ID: 3013216109

  4 TASK: 3368.Frequent values

  5 LANG: C++

  6 NOTE: 线段树

  7 */

  8 #include <cstdio>

  9 #include <algorithm>

 10 #include <cstring>

 11 #include <cmath>

 12 using namespace std;

 13 

 14 const int MAX=100005;

 15 int a[MAX],dp[MAX][18];

 16 int cnt[MAX],tree[MAX*4],f;

 17 

 18 struct trip {

 19     int s,e;

 20     int num;

 21 }wap[MAX];

 22 

 23 void build(int l,int r,int flag) {

 24     if(l==r) {

 25         tree[flag]=cnt[f++];

 26         return;

 27     }

 28     int m=(l+r)/2;

 29     build(l,m,flag*2);

 30     build(m+1,r,flag*2+1);

 31     tree[flag]=max(tree[flag<<1],tree[flag<<1|1]);

 32 }

 33 

 34 int query(int x,int y,int l,int r,int flag) {

 35     if(x<=l&&r<=y)

 36         return tree[flag];

 37     int m=(l+r)/2;

 38     int ans=0;

 39     if(x<=m)

 40         ans=max(ans,query(x,y,l,m,flag<<1));

 41     if(y>m)

 42         ans=max(ans,query(x,y,m+1,r,flag<<1|1));

 43     return ans;

 44 }

 45 

 46 int main()

 47 {

 48     int n,q,x,y,i,j;

 49     while(scanf("%d",&n),n) {

 50         scanf("%d",&q);

 51         memset(wap,0,sizeof(wap));

 52         memset(cnt,0,sizeof(cnt));

 53         int k=1;

 54         scanf("%d",&a[1]);

 55         wap[k].s=1;

 56         for(i=2;i<=n;i++) {

 57             scanf("%d",&a[i]);

 58             if(a[i]==a[i-1]) {

 59                 cnt[k]++;

 60                 wap[i].s=wap[i-1].s;

 61             }

 62             else {

 63                 cnt[k]++;

 64                 wap[i].e=i-1;

 65                 k++;

 66                 wap[i].s=i;

 67             }

 68         }

 69         wap[n+1].e=n;

 70         cnt[k]++;

 71         for(i=1,j=1;i<=n;) {

 72             for(int f=i;f<i+cnt[j];f++)

 73                 wap[f].num=j;

 74             for(int f=i+1;f<i+cnt[j];f++)

 75                 wap[f].s=wap[f-1].s;

 76             for(int f=i+cnt[j]-1;f>=i;f--)

 77                 wap[f].e=wap[f+1].e;

 78             i+=cnt[j];j++;

 79         }

 80         f=1;

 81         build(1,k,1);

 82         while(q--) {

 83             scanf("%d %d",&x,&y);

 84             int i,st,rt,ans;

 85             st=wap[x].num;

 86             rt=wap[y].num;

 87             if((rt-st)==0)

 88                 ans=y-x+1;

 89             else if((rt-st)==1)

 90                 ans=max(wap[x].e-x+1,y-wap[y].s+1);

 91             else {

 92                 ans=query(st+1,rt-1,1,k,1);

 93                 ans=max(wap[x].e-x+1,ans);

 94                 ans=max(ans,y-wap[y].s+1);

 95             }

 96             printf("%d\n",ans);

 97         }

 98     }

 99     return 0;

100 }

 

你可能感兴趣的:(value)