HDU - 5172 GTY's gay friends (线段树+前缀和)

GTY has nn gay friends. To manage them conveniently, every morning he ordered all his gay friends to stand in a line. Every gay friend has a characteristic value aiai , to express how manly or how girlish he is. You, as GTY's assistant, have to answer GTY's queries. In each of GTY's queries, GTY will give you a range [l,r][l,r] . Because of GTY's strange hobbies, he wants there is a permutation [1..r−l+1][1..r−l+1] in [l,r][l,r]. You need to let him know if there is such a permutation or not.

Input

Multi test cases (about 3) . The first line contains two integers n and m ( 1≤n,m≤10000001≤n,m≤1000000 ), indicating the number of GTY's gay friends and the number of GTY's queries. the second line contains n numbers seperated by spaces. The ithith number aiai ( 1≤ai≤n1≤ai≤n ) indicates GTY's ithith gay friend's characteristic value. The next m lines describe GTY's queries. In each line there are two numbers l and r seperated by spaces ( 1≤l≤r≤n1≤l≤r≤n ), indicating the query range.

Output

For each query, if there is a permutation [1..r−l+1][1..r−l+1] in [l,r][l,r], print 'YES', else print 'NO'.

Sample Input

8 5
2 1 3 4 5 2 3 1
1 3
1 1
2 2
4 8
1 5
3 2
1 1 1
1 1
1 2

Sample Output

YES
NO
YES
YES
YES
YES
NO

题意:

问区间[l,r]内的元素是否可以构成从1到r-l+1的一个排列。

思路:

如果可以构成,则[l,r]的区间和一定等于(r-l+1)*(r-l+2)/2

先判断区间和,符合条件的再判断区间内有无重复元素

预处理出每个数字上一次出现的位置,存入pre中,由于数据较大,所以建线段树来查找[l,r]中pre的最大值,若该值

具体实现见代码

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int N=1e6+3;

int n,m;
int pre[N],now[N];///pre[i]第i个数字上一次出现的位置(下标) now[i]当前数字的位置(qwq亲测用map会爆内存)
ll a[N];///前缀和
int cnt;

struct node
{
    int l,r,sum;///刚开始直接拿了板子抄过来,没有去掉siz(区间长度),结果爆内存了qwq
}T[4*N+1];

void update(int k)///更新区间最值
{
    T[k].sum=max(T[k*2].sum,T[k*2+1].sum);
}

void build(int k,int ll,int rr)///建树
{
    T[k].l=ll;
    T[k].r=rr;
    if(ll==rr)
    {
        T[k].sum=pre[++cnt];
        return ;
    }
    int mid=(ll+rr)/2;
    build(k*2,ll,mid);
    build(k*2+1,mid+1,rr);
    update(k);
}

int ask_sum(int k,int ll,int rr)///查询区间最值
{
    int ans=0;
    if(ll<=T[k].l&&T[k].r<=rr)
    {
        ans=max(ans,T[k].sum);
        return ans;
    }
    int mid=(T[k].l+T[k].r)/2;
    if(ll<=mid)
        ans=max(ans,ask_sum(k*2,ll,rr));
    if(rr>mid)
        ans=max(ans,ask_sum(k*2+1,ll,rr));
    return ans;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(a,0,sizeof(a));
        memset(pre,0,sizeof(pre));
        memset(T,0,sizeof(T));
        memset(now,0,sizeof(now));
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            pre[i]=now[a[i]];
            now[a[i]]=i;
            a[i]=a[i-1]+a[i];
        }
        cnt=0;
        build(1,1,n);
        int l,r;
        while(m--)
        {
            scanf("%d%d",&l,&r);
            bool flag=0;
            int len=r-l+1;
            if(a[r]-a[l-1]==len*(len+1)/2)
            {
                int tmp=ask_sum(1,l,r);
                if(tmp

 

你可能感兴趣的:(数据结构)