码迷,mamicode.com
首页 > 编程语言 > 详细

UVA - 1618 Weak Key(RMQ算法)

时间:2019-02-02 19:14:30      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:个数   col   ons   pac   cout   while   open   type   还需要   

题目:

给出k个互不相同的证书组成的序列Ni,判断是否存在4个证书Np、Nq、Nr、Ns(1≤p<q<r<s≤k)使得Nq>Ns>Np>Nr或者Nq<Ns<Np<Nr。

思路:

有两种情况<小、最大、最小、大>、<大、最小、最大、小>,枚举第1个和第4个数,用RMQ查询这两个数之间的最大值和最小值,然后根据给出的条件判断一下就可以了。

看到好多大佬不用RMQ也写出来了,还需要在研究一下。

代码:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define MAX 1e3
#define FRE() freopen("in.txt","r",stdin)
#define FRO() freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 100010;
int pos[maxn],a[maxn];
int dmin[maxn][20],dmax[maxn][20];
int mi[maxn],mx[maxn];
int n;

void InitMinRMQ(){
    mi[0] = -1;
    for(int i=1; i<=n; i++){
        mi[i] = ((i&(i-1))==0) ? mi[i-1]+1:mi[i-1];
        dmin[i][0] = a[i];
    }
    for(int j=1; j<=mi[n]; j++){
        for(int i=1; i+(1<<j)-1<=n; i++){
            dmin[i][j]=min(dmin[i][j-1], dmin[i+(1<<(j-1))][j-1]);
        }
    }
}

int MinRMQ(int x,int y){
    int k = mi[y-x+1];
    return min(dmin[x][k],dmin[y-(1<<k)+1][k]);
}

void InitMaxRMQ(){
    mx[0] = -1;
    for(int i=1; i<=n; i++){
        mx[i] = ((i&(i-1))==0) ? mx[i-1]+1:mx[i-1];
        dmax[i][0] = a[i];
    }
    for(int j=1; j<=mx[n]; j++){
        for(int i=1; i+(1<<j)-1<=n; i++){
            dmax[i][j] = max(dmax[i][j-1],dmax[i+(1<<(j-1))][j-1]);
        }
    }
}

int MaxRMQ(int x,int y){
    int k = mx[y-x+1];
    return max(dmax[x][k], dmax[y-(1<<k)+1][k]);
}


int main(){
    //FRE();
    int kase;
    scanf("%d",&kase);
    while(kase--){
        scanf("%d",&n);
        for(int i=1; i<=n; i++){
            scanf("%d",&a[i]);
            pos[a[i]] = i;
        }
        InitMaxRMQ();
        InitMinRMQ();
        //cout<<MinRMQ(1,n)<<"  "<<MaxRMQ(1,n)<<endl;
        bool ok = false;
        for(int i=1; i<n; i++){
            for(int j=i+1; j<=n; j++){
                int tmin = MinRMQ(i, j);
                int tmax = MaxRMQ(i, j);
                if(a[i]<a[j] && pos[tmax]<pos[tmin]){
                    ok = true;
                }
                if(a[i]>a[j] && pos[tmax]>pos[tmin]){
                    ok = true;
                }
            }
            if(ok)
                break;
        }
        if(ok)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}

 

UVA - 1618 Weak Key(RMQ算法)

标签:个数   col   ons   pac   cout   while   open   type   还需要   

原文地址:https://www.cnblogs.com/sykline/p/10348784.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!