zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans);
     97         }
     98     }
     99     return 0;
    100 }
  • 相关阅读:
    vim高级编辑(一)
    [每日一题] 11gOCP 1z0-052 :2013-09-5 runInstaller oracle of no swap
    ABAP 中 Table Control例子
    跟我一起学习ASP.NET 4.5 MVC4.0(四)
    跟我一起学习ASP.NET 4.5 MVC4.0(三)
    跟我一起学习ASP.NET 4.5 MVC4.0(二)
    跟我一起学习ASP.NET 4.5 MVC4.0(一)
    如何选择Html.RenderPartial和Html.RenderAction
    ASP.NET MVC4 Razor
    ADO.NET Entity Framework -Code Fisrt 开篇(一)
  • 原文地址:https://www.cnblogs.com/ACMans/p/4566787.html
Copyright © 2011-2022 走看看