区间检测(range)

区间检测(range)

时间限制: 1 Sec  内存限制: 128 MB

 

题目描述

给定一个长度为n的序列,进行m次检测,每次检测某个区间中,是否有重复的数。

输入

第一行,两个整数n和m,表示序列中元素的个数以及需要检测的次数。

第二行n个元素,表示序列中的元素。 

接下来m行,每行两个整数L和R(L≤R),表示需要检测的区间。

输出

对于每个询问,如果这个区间没有重复的数字,输出1,否则输0。

样例

5 2

1 2 3 4 1

1 4

1 5

1

0

 

提示


对于30%的数据,n和m的范围[1,500];
对于50%的数据,n和m的范围[1,5000];
对于80%的数据,n和m的范围[1,50000],序列中的元素范围[0,105];
对于100%的数据,n和m的范围[1,500000],序列中的元素范围[0,109]

 

 

这就是题目了

这个我爆蛋了。。。

其实不难,但是我还是写的题目少了
这个题面非常的清晰,就不用再解释了

判断一个区间中有没有相同的数,把他给分割成为子问题,就是判断每一个数在这个区间内有没有相同的数
那么就很自然的想到维护每一个数前面和后面相同的数在什么位置就好了qwq

可是有必要吗awa

只用维护前面的就好了qwq

仔细想想就好了awa
如果这个区间里面有一个数重复了,那么肯定会有一个数前面一个和他相同的数在这个区间中awa

所以就方便多了qwq

pre[i]表示上一个值为A[i]的数出现的位置

题目等价于判断min(pre[L...R])是否小于L

因为pre[1...L-1]显然是小于L的,所有可以直接判断min(pre[1...R])是否小于L

快乐

code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,a[5000001],Max[500001][30];
map<int,int>pre;
inline ll read()
{
    char c=getchar();ll a=0,b=1;
    for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1;
    for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48;
    return a*b;
}
ll ask(ll l,ll r)
{
    ll k=log2(r-l+1);
    return max(Max[l][k],Max[r-(1<<k)+1][k]);
}
void work()
{
    int t=log2(n);
    for(ll j=1;j<=t;j++)
    {
        for(ll i=1;i<=n-(1<<j)+1;i++)
        {
            Max[i][j]=max(Max[i][j-1],Max[i+(1<<(j-1))][j-1]);
        }
    }
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
    {
        int val=read();
        Max[i][0]=pre[val];
        pre[val]=i;
    }
    work();
    while(m--)
    {
        int l=read(),r=read();
        if(ask(l,r)<l) puts("1");
        else puts("0");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/HLZZPawa/p/13503958.html