您的位置:首页 > 其它

hdu 5172 GTY's gay friends (线段树||hash)

2015-02-10 09:50 441 查看
题意:

n个数m个询问,询问(l,r)中的数是否为1 ~ r-l+1的一个排列。

分析:

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

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

2、区间内的数字各不相同,即用线段树维护位置i上的数上次出现的位置的最大值。

只要区间内所有的数上次出现的位置last[i] < l,则区间内的数各不相同。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<map>

using namespace std;

typedef long long ll;
const int maxn = 1000010;

ll sum[maxn];
int tre[maxn<<2];
int last[maxn],pos[maxn];

void PushUp(int rt)
{
    tre[rt] = max(tre[rt<<1],tre[rt<<1|1]);
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        tre[rt] = last[l];
        return;
    }
    int mid = (l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    PushUp(rt);
}
ll query(int rt,int l,int r,int q1,int q2){
    if(q1<=l && r<=q2) return tre[rt];
    int mid = (l+r)>>1;
    ll ret = 0;
    if(q1<=mid) ret = max(ret,query(rt<<1,l,mid,q1,q2));
    if(q2>mid) ret = max(ret,query(rt<<1|1,mid+1,r,q1,q2));
    return ret;
}

int main()
{
    int n,m,x;
    while(~scanf("%d%d",&n,&m))
    {
        memset(sum,0,sizeof(sum));
        memset(pos,0,sizeof(pos));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            sum[i] = sum[i-1]+x;
            last[i] = pos[x];
            pos[x] = i;
        }
        build(1,1,n);
        ll l,r;
        while(m--){
            scanf("%I64d%I64d",&l,&r);
            ll len = r-l+1;
            if((sum[r]-sum[l-1]==len*(len+1)/2) && query(1,1,n,l,r)<l) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}


hash做法:

对于[1-n]中的每一个数随机一个64位无符号整型作为它的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(int argc,char const *argv[])
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: