设为首页 加入收藏

TOP

hdu 5172 RMQ
2015-07-20 17:19:10 来源: 作者: 【 】 浏览:2
Tags:hdu 5172 RMQ

题意: 给出一个数组a[n](1<=a[i]<=n),可能会有重复,然后m组询问
每次询问两个数:l,r
在区间[l,r]内是否构成一个1,2,..,r-l+1的排列;
分析: 要想构成1,2….r-l+1的排列,首先要满足区间内的和sum=(1+len)*len/2
然后区间内的每个数都不一样即可,然后再开一个数组记录每个数前一次出现的位置pre,如果[l,r]内pre的最大值都小于l,那就行了;
基于线段树的rmq

/*
    基于线段树(完美线段树)的RMQ问题~!
*/

#include 
   
     #include 
    
      #include 
     
       #include 
      
        #include 
       
         using namespace std; const int N=1e6+100; const int INF=-999999; typedef long long ll; ll sum[N]; int vis[N]; int pre[N]; int dat[2*N],nn; //线段树 void init(int n_) //初始化 O(n) { nn=1; while(nn
        
         0) { k=(k-1)/2; dat[k]=max(dat[k*2+1],dat[k*2+2]); } } int query(int a,int b,int k,int l,int r) { if(b<=l || r<=a)return INF; //区间没有交集 if(a<=l&&r<=b)return dat[k]; else { int v1=query(a,b,k*2+1,l,(l+r)/2); int v2=query(a,b,k*2+2,(l+r)/2,r); return max(v1,v2); } } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { init(n); memset(vis,-1,sizeof(vis)); for(int i=1;i<=n;i++) { int a; scanf("%d",&a); sum[i]=sum[i-1]+a; if(vis[a]==-1) { pre[i]=-1; vis[a]=i; } else { pre[i]=vis[a]; vis[a]=i; } } for(int i=1;i<=n;i++) { update(i-1,pre[i]); } while(m--) { int l,r; scanf("%d%d",&l,&r); ll tmp1=(r-l+2)*(r-l+1)/2; if(tmp1==(sum[r]-sum[l-1])) { //cout<
         
        
       
      
     
    
   
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇spring之jdbcTemplate实例 下一篇rockethon2015 C题 Second price ..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何理解c语言指针和 (2025-12-27 01:19:11)
·为什么C标准库没有链 (2025-12-27 01:19:08)
·玩转C语言和数据结构 (2025-12-27 01:19:05)
·MySQL 基础入门视频 (2025-12-26 23:20:22)
·小白入门:MySQL超详 (2025-12-26 23:20:19)