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

 

原文地址:https://www.cnblogs.com/lienus/p/4281194.html