zoukankan      html  css  js  c++  java
  • POJ3368 Frequent values(RMQ线段树)

    题目大概说给一个递增序列,询问区间出现最多的数。

    用莫队算法比较直观,虽然应该会T。。好像也可以主席树。。不过题目给的序列是有序的,因而相同的数会聚在一起。

    考虑把序列分成一段一段,使每段都包含极大的相同的数字

    这样对于每一个区间查询:

      • 可能这个区间左边或右边没有包含完整的一段,而其长度在段里对左或右端点进行二分查找就知道了
      • 而除去两边不完整的,还要求出中间若干完整段的最大长度,这个就是用RMQ来快速解决了

    于是这题就能这样解决了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define MAXN 222222
     6 
     7 int lrec[MAXN],rrec[MAXN];
     8 
     9 int tree[MAXN<<2],N,x,y;
    10 void update(int i,int j,int k){
    11     if(i==j){
    12         tree[k]=y;
    13         return;
    14     }
    15     int mid=i+j>>1;
    16     if(x<=mid) update(i,mid,k<<1);
    17     else update(mid+1,j,k<<1|1);
    18     tree[k]=max(tree[k<<1],tree[k<<1|1]);
    19 }
    20 int query(int i,int j,int k){
    21     if(x>y) return 0;
    22     if(x<=i && j<=y){
    23         return tree[k];
    24     }
    25     int mid=i+j>>1,res=0;
    26     if(x<=mid) res=max(res,query(i,mid,k<<1));
    27     if(y>mid) res=max(res,query(mid+1,j,k<<1|1));
    28     return res;
    29 }
    30 
    31 int seq[MAXN];
    32 int main(){
    33     int n,q,a,b;
    34     while(~scanf("%d",&n) && n){
    35         scanf("%d",&q);
    36         for(int i=1; i<=n; ++i){
    37             scanf("%d",seq+i);
    38         }
    39         seq[n+1]=111111;
    40 
    41         int rn=0;
    42         lrec[0]=1;
    43         for(int i=1; i<=n+1; ++i){
    44             if(seq[i]!=seq[i+1]){
    45                 rrec[rn]=i;
    46                 rn++;
    47                 lrec[rn]=i+1;
    48             }
    49         }
    50 
    51         memset(tree,0,sizeof(tree));
    52         for(N=1; N<rn; N<<=1);
    53         for(int i=0; i<rn; ++i){
    54             x=i; y=rrec[i]-lrec[i]+1;
    55             update(0,N-1,1);
    56         }
    57 
    58         int i,j,res;
    59         while(q--){
    60             scanf("%d%d",&a,&b);
    61             i=lower_bound(rrec,rrec+rn,a)-rrec;
    62             j=upper_bound(lrec,lrec+rn,b)-lrec-1;
    63             if(rrec[i]>=b){
    64                 printf("%d
    ",b-a+1);
    65                 continue;
    66             }
    67             res=max(rrec[i]-a+1,b-lrec[j]+1);
    68             x=i+1; y=j-1;
    69             res=max(res,query(0,N-1,1));
    70             printf("%d
    ",res);
    71         }
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    matlab read txt
    matlab读取数据并操作
    NFS 共享信息泄露漏洞
    centos6.8环境下安装elasticdump进行elasticsearch索引结构mapping的备份
    Linux命令行下如何终止当前程序
    ubuntu 使用sudo vim /etc/apt/sources.list命令修改文件后该如何退出?
    隐写工具zsteg安装及使用教程
    【转】今天做CTF隐写术的题偶然发现一隐写图片查看的神器------stegsolve,分享给大家
    java安装及配置环境变量
    deepin使用root身份运行
  • 原文地址:https://www.cnblogs.com/WABoss/p/5491338.html
Copyright © 2011-2022 走看看