• hdoj6483 A Sequence Game(ST预处理RMQ+莫队)


    传送:http://acm.hdu.edu.cn/showproblem.php?pid=6483

    题意:有长度为$n$的数组,对于一个子区间$[l,r]$内,存在最大值$mx$与最小值$mi$,有$q$的询问,每个询问要求判断在某个子区间$[l,r]$内$[mi,mx]$的值是否连续存在,即$mi,mi+1,....,mx$每个数都出现过至少一次。$T=5,1<=n<=10000,1<=a_i<=10^9,1<=m<=100000$

    分析:

    多个区间查询问题,考虑莫队算法。

    对于每一个询问,需要判断$mi$到$mx$内的数是否全部存在,且需要知道$mi$与$mx$。考虑先预处理出每个子区间的最值,离线查询。

    $a_i<=10^9$,数组$num[]$没办法开下,需要离散化处理。

    先ST预处理最值,然后离散化,莫队求区间内值种类的个数。

    代码:

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+10;
     4 struct node{
     5     int l,r,id,block,mx,mi;
     6 }q[maxn];
     7 int a[maxn],b[maxn],maxPoint[maxn][30],minPoint[maxn][30],num[maxn];
     8 bool ans[maxn];
     9 int cnt=0,n,m,block,ll,rr;
    10 bool cmp(node p,node q){
    11     return p.block<q.block || p.block==q.block && p.r<q.r;
    12 }
    13 void add(int x){
    14     int tmp=a[x];
    15     if (num[tmp]==0) cnt++;
    16     num[tmp]++;
    17 }
    18 void del(int x){
    19     int tmp=a[x];
    20     if (num[tmp]==1) cnt--;
    21     num[tmp]--;
    22 }
    23 void init(){
    24     for (int i = 1; i <= n; i++){
    25         minPoint[i][0] = maxPoint[i][0] = a[i];
    26     }
    27     for (int j = 1; (1 << j) <= n; j++){
    28         for (int i = 1; i + (1 << j) - 1 <= n; i++){
    29             int p = (1 << (j - 1));
    30             minPoint[i][j] = min(minPoint[i][j - 1], minPoint[i + p][j - 1]);
    31             maxPoint[i][j] = max(maxPoint[i][j - 1], maxPoint[i + p][j - 1]);
    32         }
    33     }
    34 }
    35 int queryMin(int l, int r){
    36     int k = log2((double)(r - l + 1));
    37     return min(minPoint[l][k], minPoint[r - (1 << k) + 1][k]);
    38 }
    39 
    40 int queryMax(int l, int r){
    41     int k = log2((double)(r - l + 1));
    42     return max(maxPoint[l][k], maxPoint[r - (1 << k) + 1][k]);
    43 }
    44 bool calc(node tmp){
    45     if (tmp.mx-tmp.mi+1==cnt) return true;
    46     return false;
    47 }
    48 void init2(){
    49     sort(b+1,b+1+n);
    50     int tmp=unique(b+1,b+1+n)-(b+1);
    51     for (int i=1;i<=n;i++){
    52         a[i]=lower_bound(b+1,b+1+tmp,a[i])-b;
    53         num[i]=0;
    54     }
    55 } 
    56 int main(){
    57     int t; scanf("%d",&t);
    58     while (t--){
    59         scanf("%d%d",&n,&m);
    60         for (int i=1;i<=n;i++){
    61             scanf("%d",&a[i]);
    62             b[i]=a[i];
    63         }
    64         init();
    65         //离散化
    66         block=sqrt(n);
    67         for (int i=0;i<m;i++){
    68             scanf("%d%d",&q[i].l,&q[i].r);
    69             q[i].id=i; q[i].block=q[i].l/block;
    70             q[i].mx=queryMax(q[i].l,q[i].r);
    71             q[i].mi=queryMin(q[i].l,q[i].r);
    72         }
    73         init2();
    74         sort(q,q+m,cmp);
    75         ll=1,rr=0; cnt=0;
    76         for (int i=0;i<m;i++){
    77             while (ll<q[i].l) del(ll++);
    78             while (ll>q[i].l) add(--ll);
    79             while (rr<q[i].r) add(++rr);
    80             while (rr>q[i].r) del(rr--); 
    81             ans[q[i].id]=calc(q[i]);
    82         }
    83         for (int i=0;i<m;i++)
    84             if (ans[i]) printf("YES
    ");
    85             else printf("NO
    ");
    86     }
    87     return 0;
    88 } 
    hdoj6483
  • 相关阅读:
    c++学习--面向对象一实验
    c++学习--面向对象一
    c#学习
    Linux安全之SSH 密钥创建及密钥登录,禁止密码登陆
    laravel 5.5 跨域问题 并且laravel的跨域 Access-Control-Allow-Origin 报错的坑
    安装 lnmp
    微信小程序-聊天功能下拉加载更多数据(历史聊天内容出现在顶部)
    简单实现小程序view拖拽功能
    mysql 常用命令
    有感而发——写给曼曼的信
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/10719824.html
Copyright © 2020-2023  润新知