• HDU


    题目链接

    题意:n个数m个查询,问[l,r]中的数是否为1到r-l+1的一个排列。

    做法1:
    hash一下,对于[1...n],每个数都随机分配一个hash值,一个集合的hash值为元素异或和。预处理出[1...n]的hash值及其前缀的hash,然后就可以O(1)查询了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<map>
    #include<ctime>
    #define eps (1e-8)
    
    using namespace std;
    
    typedef long long ll;
    unsigned long long ra[1000005],a[1000005],ha[1000005];
    int n,m,t,p;
    
    int main()
    {
        srand(time(NULL));
        a[0] = ha[0] = 0;
        for(int i=1; i<=1000000; i++)
        {
            ra[i] = rand()*rand();
            ha[i] = ha[i-1]^ra[i];
        }
        while(~scanf("%d%d",&n,&m))
        {
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&t);
                a[i] = ra[t];
                a[i]^=a[i-1];
            }
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d",&t,&p);
                puts((ha[p-t+1]==(a[p]^a[t-1])?"YES":"NO"));
            }
        }
        return 0;
    }

    做法二:线段树
    若(l,r)中的数为1 ~ r-l+1中的一个排列,则必须满足:

    1、(l,r)中的数之和为len*(len+1)/2,其中len = r-l+1。

    2、区间内的数字各不相同,即用线段树维护位置i上的数上次出现的位置的最大值。只要区间内所有的数上次出现的位置last[i] < l,则区间内的数各不相同。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #include <math.h>
    using namespace std;
    typedef long long LL;
    const int N = 1000005;
    int pre[N],now[N];
    LL sum[N];
    struct Tree{
        int MAX_ID;
    }tree[N<<2];
    int MAX_ID;
    void PushUp(int idx){
        tree[idx].MAX_ID = max(tree[idx<<1].MAX_ID,tree[idx<<1|1].MAX_ID);
    }
    void build(int l,int r,int idx){
        if(l==r){
            tree[idx].MAX_ID = pre[l];
            return;
        }
        int mid = (l+r)>>1;
        build(l,mid,idx<<1);
        build(mid+1,r,idx<<1|1);
        PushUp(idx);
    }
    void query(int l,int r,int L,int R,int idx){
        if(l >= L&& r <= R){
            MAX_ID = max(MAX_ID,tree[idx].MAX_ID);
            return;
        }
        int mid = (l+r)>>1;
        if(mid>=L) query(l,mid,L,R,idx<<1);
        if(mid<R)  query(mid+1,r,L,R,idx<<1|1);
    }
    int main()
    {
        int n,k;
        while(scanf("%d%d",&n,&k)!=EOF){
            memset(now,0,sizeof(now));
            sum[0] = 0;
            for(int i=1;i<=n;i++){
                int x;
                scanf("%d",&x);
                sum[i] = sum[i-1]+x;
                pre[i] = now[x];
                now[x] = i;
            }
            build(1,n,1);
            while(k--){
                int l,r;
                scanf("%d%d",&l,&r);
                LL len = r-l+1;
                LL S = (len+1)*(len)/2;
                if(sum[r]-sum[l-1]!=S){
                    printf("NO
    ");
                    continue;
                }
                MAX_ID = -1;
                query(1,n,l,r,1);
                if(MAX_ID<l) printf("YES
    ");
                else printf("NO
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    【转】extern "C"的含义和用法
    python的shelve库
    【转】TCP是流传输协议,UDP是包传输协议
    【转】TCP慢启动、拥塞避免、快速重传、快速恢复
    【转】C/C++多线程编程中什么情况下需要加volatile?
    【转】C++对象是创建在堆上,还是在栈上?
    【转】腾讯高级工程师:一道面试题引发的高并发性能调试思考
    【转】C++类的sizeof大小
    【转】C编译器内存对齐
    【转】c++中使用memset初始化类对象
  • 原文地址:https://www.cnblogs.com/fht-litost/p/7257524.html
Copyright © 2020-2023  润新知