HDU 3833 YY's new problem (hash)

YY's new problem

Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3158    Accepted Submission(s): 890


Problem Description
Given a permutation P of 1 to N, YY wants to know whether there exists such three elements P[i 1], P[i 2], P[i 3] that 
P[i 1]-P[i 2]=P[i 2]-P[i 3], 1<=i 1<i 2<i 3<=N.
 

 

Input
The first line is T(T<=60), representing the total test cases.
Each test case comes two lines, the former one is N, 3<=N<=10000, the latter is a permutation of 1 to N.
 

 

Output
For each test case, just output 'Y' if such i 1, i 2, i 3 can be found, else 'N'.
 

 

Sample Input
2 3 1 3 2 4 3 2 4 1
 

 

Sample Output
N Y
 

 

Source
 

 

Recommend
xubiao

 

一是利用二级排序,二是利用hash表。先说说hash表吧。既然要找到1到n序列中是否存在满足题意的三个元素,注意这三个元素有先后顺序之分,可以用一个数组来模拟。首先将数组全部清0,然后开始读入元素i,每读入一个元素就将以该元素为下标的hash表中的元素加1,即hash[i]++,然后在hash表中寻找,在hash[i]的对称的前面和后面查找,如果hash[i-j]+hash[i+j]==1, 说明在i出现时,有两种可能,一是比i小的数已经出现但比i大的数还没出现,或者比i大的数已经出现,比i小的数还没出现,没出现的数在i的后面,已经出现的在i的前面,这就找到了满足题意的序列。

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int n,hash[20010];

int main(){

    //freopen("input.txt","r",stdin);

    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        memset(hash,0,sizeof(hash));
        int flag=0,x;
        for(int k=1;k<=n;k++){
            scanf("%d",&x);
            hash[x]++;
            if(flag==0){
                for(int i=1;i<x && i+x<=n;i++)
                    if(hash[x-i]+hash[x+i]==1){
                        flag=1;
                        break;
                    }
            }
        }
        if(flag)
            printf("Y\n");
        else
            printf("N\n");
    }
    return 0;
}

 

这个算法应用范围更广:

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

int n,num[10010];

int main(){

    //freopen("input.txt","r",stdin);

    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        int x;
        for(int i=1;i<=n;i++){
            scanf("%d",&x);
            num[x]=i;
        }
        int lim=2*(n-1),flag=0;
        for(int i=4;i<=lim && !flag;i+=2){
            for(int j=(i>n?i-n:1);j<(i>>1);j++){
                int k=i-j;
                if((num[j]-num[i>>1])*(num[i>>1]-num[k])>0){
                    flag=1;
                    break;
                }
            }
        }
        if(flag)
            printf("Y\n");
        else
            printf("N\n");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/jackge/archive/2013/05/23/3094662.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值