• Frequent values


    poj3368:http://poj.org/problem?id=3368

    题意:给你一个非下降的序列,然后查询[l,r]内出现最多数字的次数。

    题解:首先,因为序列是非下降的,所以相同的数字出现在在一起。所以,可以定义一个数组a[i]=k,表示第i个数出现的次数,另外还要记录几个东西,ll[i],rr[i],分别表示第i个数首次出现的位置和最后出现的位置。sum[i]到第i数出现结束之后一共有多少个数。准备好了这些东西之后。既可以开始了。第一步以数的个数(相同的算一个)建立线段树,叶子节点的值就是这个数出现的次数,然后维护区间最大值。2对于一个查询来说,是查询第几个数到第几个数之间出现的最大值的话,问题就爱很简单了。所以,我们要把查询转化成这样的就行了。query(l,r),我们可以通过lower_bound(sum+1,sum+temp+1)-sum,来找到l,r出现在第几个数中,然后我们查询l后面和r前面的数就可以啦 啊。对于l前面的部分,肯定是连续的,所以可以直接ll[l+1]-u得到左边的,v-rr[ed-1]得到右边的,然后3部分去最大值就可以啦。当然还有几个情况,就是1:l,r出现在同一个数中,那么可以直接u-v+1,如果是相隔一个数的话,max(sum[l]-u+1,v-sum[ed-1])即可。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=1e5+5;
     7 int ll[N],rr[N],sum[N];
     8 int maxn[N*4];
     9 int a[N];
    10 int n,q,temp;
    11 void input(){
    12     int t,tp;
    13      scanf("%d",&t);
    14      a[temp]=1;
    15      ll[temp]=1;
    16   for(int i=2;i<=n;i++){
    17     scanf("%d",&tp);
    18     if(tp==t)a[temp]++;
    19     else{
    20         a[++temp]=1;
    21         ll[temp]=i;
    22         rr[temp-1]=i-1;
    23         t=tp;
    24     }
    25   }
    26   rr[temp]=n;
    27 }
    28 void build(int l,int r,int rt){
    29     if(l==r){
    30         maxn[rt]=a[l];
    31         return;
    32     }
    33    int mid=(l+r)/2;
    34    build(l,mid,rt<<1);
    35    build(mid+1,r,rt<<1|1);
    36    maxn[rt]=max(maxn[rt<<1],maxn[rt<<1|1]);
    37 }
    38 int query(int l,int r,int rt,int from,int to){
    39    if(l==from&&r==to){
    40     return maxn[rt];
    41    }
    42    int mid=(l+r)/2;
    43    if(mid>=to)return query(l,mid,rt<<1,from,to);
    44    else if(mid<from)return query(mid+1,r,rt<<1|1,from,to);
    45    else{
    46     return max(query(l,mid,rt<<1,from,mid),query(mid+1,r,rt<<1|1,mid+1,to));
    47    }
    48 }
    49 int u,v;
    50 int main(){
    51     while(~scanf("%d",&n)){
    52         if(n==0)break;
    53          scanf("%d",&q);
    54          temp=1;
    55          input();
    56         memset(maxn,0,sizeof(maxn));
    57         build(1,temp,1);
    58         sum[0]=0;
    59         for(int i=1;i<=temp;i++){
    60             sum[i]=sum[i-1]+a[i];
    61         }
    62         for(int i=1;i<=q;i++){
    63             scanf("%d%d",&u,&v);
    64             int st=lower_bound(sum+1,sum+temp+1,u)-sum;
    65             int ed=lower_bound(sum+1,sum+temp+1,v)-sum;
    66             st++;ed--;
    67             if(ed>=st){
    68                 int ans1=query(1,temp,1,st,ed);
    69                 int ans2=ll[st]-u;
    70                 int ans3=v-rr[ed];
    71                 printf("%d
    ",max(ans1,max(ans2,ans3)));
    72             }
    73             else if(st==ed+2){
    74                 printf("%d
    ",v-u+1);
    75             }
    76             else{
    77                 st--,ed++;
    78                 printf("%d
    ",max(sum[st]-u+1,v-sum[ed-1]));
    79             }
    80         }
    81 
    82     }
    83 }
    View Code
  • 相关阅读:
    贪婪算法、递归计算、动态规划背包问题
    递归、动态规划计算斐波那契数列
    用于确定两个字符串最长公共子串的函数
    快速排序算法
    顺序、二分查找文本数据
    MyBatis面试题
    Spring面试题
    SpringMvc面试题
    jsp和servlet面试
    EJB的理解
  • 原文地址:https://www.cnblogs.com/chujian123/p/3870558.html
Copyright © 2020-2023  润新知