hdu5172(线段树)

 

传送门:GTY's gay friends

题意:判断区间[l,r]内的数字是否符合1~len(r-l+1)的一个全排列。

分析:pos[i]记录数字i出现的最大位置,pre[i]记录在位置i的数字a[i]出现的最大位置,然后每次判断区间内数字全不同且区间和为(len+1)*len就是一个全排列了。

至于求区间内相同数字出现的最大位置,用线段树维护区间最值即可。

#include <cstdio>

#include <cstring>

#include <string>

#include <cmath>

#include <iostream>

#include <algorithm>

#include <queue>

#include <cstdlib>

#include <stack>

#include <vector>

#include <set>

#include <map>

#define LL long long

#define mod 100000000

#define inf 0x3f3f3f3f

#define eps 1e-6

#define N 1000010

#define FILL(a,b) (memset(a,b,sizeof(a)))

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

#define PII pair<int,int>

using namespace std;

int pos[N],pre[N],a[N],mx[N<<2];

LL sum[N];

void Pushup(int rt)

{

    int ls=rt<<1,rs=ls|1;

    mx[rt]=max(mx[ls],mx[rs]);

}

void build(int l,int r,int rt)

{

    if(l==r)

    {

        mx[rt]=pre[l];

        return;

    }

    int m=(l+r)>>1;

    build(lson);

    build(rson);

    Pushup(rt);

}

int query(int L,int R,int l,int r,int rt)

{

    if(L<=l&&r<=R)

        return mx[rt];

    int m=(l+r)>>1;

    int res=0;

    if(L<=m)res=max(res,query(L,R,lson));

    if(m<R)res=max(res,query(L,R,rson));

    return res;

}

int main()

{

    int n,m,x,l,r;

    while(scanf("%d%d",&n,&m)>0)

    {

        FILL(pos,0);

        for(int i=1;i<=n;i++)

        {

            scanf("%d",&x);

            sum[i]=sum[i-1]+x;

            pre[i]=pos[x];

            pos[x]=i;

        }

        build(1,n,1);

        while(m--)

        {

            scanf("%d%d",&l,&r);

            LL len=r-l+1;

            if(sum[r]-sum[l-1]==len*(len+1)/2&&query(l,r,1,n,1)<l)

                puts("YES");

            else puts("NO");

        }

    }

}
View Code

 

 

你可能感兴趣的:(HDU)