2013北邮计算机考研复试上机题解

时间限制 1000 ms  内存限制 65536 KB

题目描述

请你计算出第 X Y Z 日是第X年的第几天。其中,1月1日是第一天,1月2日是第二天,以此类推。

计算时请注意闰年的影响。对于非整百年,年数能整除4是闰年,否则不是闰年;对于整百年,年数能整除400是闰年,否则不是闰年。如1900年和1901年不是闰年,而2000年和2004年是闰年。

输入格式

第一行有一个整数 T   (T100) ,表示一共有T组数据需要你处理。
接下来一共有T行,每行是一个如下格式的字符串: X : Y : Z ,表示你需要计算第 X Y Z 日是第 X 年的第几天。其中 X 是一个大于0,小于2100的整数。保证字符串的格式都是合法的,字符串所表示的日期也都是存在的。

输出格式

对于每组数据,你需要输出一个整数,表示所求得的结果。

输入样例

2
2013:4:12
112:4:12

输出样例

102
103

题目地址:A.日期

解题思路:

分闰年平年处理。

AC代码:
#include<iostream>
#include<cstdio>
using namespace std;

int d[2][12]= {{31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31}};

int isleap(int y)
{
    if(y%400==0||(y%4==0&&y%100!=0))	return 1;
    return 0;
}

int main()
{
    int n,i;
    int res;
    int year,month,day;
    while(~scanf("%d",&n))
    {
        while(n--)
        {
            scanf("%d:%d:%d",&year,&month,&day);
            res=day;

            int t=isleap(year);
            for(i=1; i<month; i++)
            {
                res+=d[t][i-1];
            }
            printf("%d\n",res);
        }
    }
}

时间限制 1000 ms  内存限制 65536 KB

题目描述

给出一棵有向树,一共有 N ( 1<N1000 )个节点,如果一个节点的度(入度+出度)不小于它所有儿子以及它父亲的度(如果存在父亲或儿子),那么我们称这个节点为p节点,现在你的任务是统计p节点的个数。

如样例,第一组的p节点为1,2,3;第二组的p节点为0。

输入格式

第一行为数据组数 T ( 1T100 )。
每组数据第一行为 N 表示树的节点数。后面为 N1 行,每行两个数 x , y ( 0x,y<N ),代表 y x 的儿子节点。

输出格式

每组数据输出一行,为一个整数,代表这棵树上p节点的个数。

输入样例

2
5
0 1
1 2
2 3
3 4
3
0 2
0 1

输出样例

3
1
题目地址: B.统计节点个数

解题思路:

题目的意思就是节点的度数如果
1)大于等于他每个父亲节点的度
2)并且大于等于他每个孩子节点的度,
那么就是p节点。

因此简化思路,只用统计每个节点的度即可。
由于每次给出关系就是父子关系。那么就没有必要真正建树。只需要简单统计每个节点度数即可。然后用vector把每个节点的父亲和孩子存起来。最后判断每个节点是不是p节点。然后计数

AC代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define maxn 1005
using namespace std;

vector <int> mq[maxn];
int cnt[maxn];

int main()
{
    int tes;
    int n,i,j;
    while(~scanf("%d",&tes))
    {
        while(tes--)
        {
            memset(cnt,0,sizeof(cnt));
            for(i=0; i<maxn; i++)
                mq[i].clear();
            int res=0;
            int a,b;
            scanf("%d",&n);
            for(i=0; i<n-1; i++)
            {
                scanf("%d%d",&a,&b);
                mq[a].push_back(b);
                mq[b].push_back(a);
                cnt[a]++;
                cnt[b]++;
            }

            for(i=0; i<n; i++)
            {
                int flag=0;
                for(j=0; j<mq[i].size(); j++)
                {
                    if(cnt[i]<cnt[mq[i][j]])
                    {
                        flag=1;
                        break;
                    }
                }
                if(!flag)
                    res++;
            }

            printf("%d\n",res);
        }
    }
}

/*
2
5
0 1
1 2
2 3
3 4
3
0 2
0 1
*/

时间限制 1000 ms  内存限制 65536 KB

题目描述

给出一个序列,判断该序列是不是某二叉搜索树的中序遍历序列,如果是输出"Yes",否则输出"No"。
一颗带权二叉树是一颗二叉搜索树(二叉排序树),当且仅当对于任意一个节点,他的左子树中的所有权值小于当前节点的权值,且它的右子树中的所有权值均大于当前节点的权值。

输入格式

第一行 T (T10) 代表数据组数。
每组数据包括两行:
第一行为一个整数 N (1N 400) ,表示序列的长度。
第二行包含 N 个整数,表示这个这个序列,序列中的数的 x 范围为 (1x100000)

输出格式

每组数据,如果是二叉搜索树的中序遍历序列输出"Yes",否则输出"No"。

输入样例

2
4
1 2 3 4
4
1 3 2 4

输出样例

Yes
No
题目地址: C.中序遍历序列

解题思路:

由于二叉排序树的中序遍历序列是有序的,且此题的要求必须是递增。

AC代码:
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define maxn 1005
using namespace std;

int a[maxn];

int main()
{
    int tes;
    int n,i;
    while(~scanf("%d",&tes))
    {
        while(tes--)
        {
            scanf("%d",&n);
            for(i=0; i<n; i++)
                scanf("%d",&a[i]);

            int flag=0;
            for(i=1; i<n; i++)
            {
                if(a[i]<=a[i-1])
                {
                    flag=1;
                    break;
                }
            }

            if(flag) printf("No\n");
            else printf("Yes\n");
        }
    }
}

/*
2
4
1 2 3 4
4
1 3 2 4
*/

时间限制 1000 ms  内存限制 65536 KB

题目描述

给定一个由小写字母a到z组成的字符串S,其中第i个字符为S[i](下标从0开始)。你需要完成下面两个操作:
INSERT c
其中c是一个待输入的字符。你需要在字符串的末尾添加这个字符。保证输入的字符同样是a到z之间的一个小写字母。
QUERY x
其中x是一个输入的整数下标。对于这个询问,你需要回答在S当中和S[x]相等且与x最近的距离。输入保证x在当前字符串中合法。
例如S = "abcaba",如果我们操作:
INSERT a    
则在S的末端加一个字符a,S变成"abcabaa"。
接下来操作
QUERY 0
由于S[0] = a,在S中出现的离他最近的a在下标为3的位置上,距离为3 - 0 = 3。因此应当输出3。
接下来,如果
QUERY 4
S[4] = b,S中离它最近的b出现在下标为1处,距离为4 - 1 = 3。同样应当输出3。
给定初始字符串S和若干操作,对于每个QUERY,你需要求出相应的距离。

HINT 由于输入数据较大,C/C++中推荐使用scanf进行读入以获得更快的读入速度。同时请注意算法复杂度。

输入格式

输入的第一行是一个正整数 T ( T20 ),表示测试数据的组数。
每组输入数据的第一行是一个初始串S。第二行是一个正整数 m ( 1m100000 ),表示总共操作的数量。接下来m行,每行表示一个操作。操作的格式如上所述。
数据保证在任何情况下,S的长度不会超过100000。

输出格式

对于每个QUERY,输出所求的最小距离。如果S中其它位置都不存在和它相同的字符,输出-1。

输入样例

2
axb
3
INSERT a
QUERY 0
QUERY 1
explore
3
INSERT r
QUERY 7
QUERY 1

输出样例

3
-1
2
-1
题目地址: D.最小距离查询

解题思路:

最开始的想法就是很简单的,把字符串存起来。然后INSERT的话就加到后边,QUERY的话就找到那个字符串的额位置然后向两边查找,找到最近的。不过超时了。

于是看了下题目的数据,字符串可能有10^5,QUERY的个数也可能有10^5。我这样复杂度是10^10。肯定会超时。

开始换思路。

我想到了把a-z的存在的位置都存到一个数组里,然后QUERY d的时候,先用二分找到d在字符数组里的相对位置。然后看看邻近的位置是哪个。
这样复杂度降到了10^5*log2(10^5)*20(最多有20组数据)
不过这样还是超时了。

于是开始石化了。。

最后找了个朋友商量了下。

采用hash的思想。复杂度就变成了10^5*20

每次来一个字符,

1)这个字符如果之前没出现过,就更新下这个字符的pos位置,然后dis表示最短距离更新为maxn

2)这个字符如果出现过,pos里面出现的就是离他最近的,然后dis[当前节点位置]=(当前节点位置-pos这个字符最近出现的位置)。如果dis[pos这个字符最近出现的位置]<dis[当前节点位置],更新dis[pos这个字符最近出现的位置]

详见代码:

AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 200005
using namespace std;

char str[maxn];
int pos[26];
int dis[maxn];

void getdis(int cur)
{
    int t=str[cur]-'a';
    if(pos[t]==-1)
    {
        pos[t]=cur;
        dis[cur]=maxn;
    }
    else
    {
        dis[cur]=cur-pos[t];
        if(dis[pos[t]]>dis[cur])
            dis[pos[t]]=dis[cur];
        pos[t]=cur;
    }
}

int main()
{
    int tes,len,i,n;

    char op[15];
    while(~scanf("%d",&tes))
    {
        while(tes--)
        {
            scanf("%s",str);
            len=strlen(str);

            for(i=0; i<26; i++)
                pos[i]=-1;
            for(i=0; i<len; i++)
                getdis(i);

            scanf("%d",&n);
            while(n--)
            {
                scanf("%s",op);
                if(strcmp(op,"INSERT")==0)
                {
                    char s[2];
                    scanf("%s",s);
                    str[len]=s[0];
                    getdis(len);
                    len++;
                }
                else
                {
                    int x;
                    scanf("%d",&x);
                    if(dis[x]<maxn) printf("%d\n",dis[x]);
                    else printf("-1\n");
                }
            }
        }
    }
}

/*
2
axb
3
INSERT a
QUERY 0
QUERY 1
explore
3
INSERT r
QUERY 7
QUERY 1
*/


另附上二分超时代码:
#include<stdio.h>
#include<string.h>
#include<math.h>

char str[100010];

int len;
int a[26][100010];    //记录a-z字母的位置
int l[26];    //记录a-z的个数

int find(int d,int pos)   //寻找哪个字母,哪个位置
{
    int left=0,right=l[d]-1;
    int mid;
    while(left<=right)
    {
        mid=(left+right)/2;
        if(a[d][mid]==pos)
            break;
        else if(a[d][mid]<pos)
            left=mid+1;
        else
            right=mid-1;
    }

    int res;
    if(mid-1>=0)
        res=a[d][mid]-a[d][mid-1];
    if(mid+1<l[d]&&res>a[d][mid+1]-a[d][mid])
        res=a[d][mid+1]-a[d][mid];
    return res;
}

int main()
{
    int t;

    while(scanf("%d",&t)!=EOF&&t)
    {
        while(t--)
        {
            //getchar();
            scanf("%s",str);
            len=strlen(str);
            memset(l,0,sizeof(l));

            for(int i=0; i<len; i++)
            {
                t=str[i]-'a';
                a[t][l[t]++]=i;
            }

            int m;
            scanf("%d",&m);
            for(int i=0; i<m; i++)
            {
                char s[10];
                //getchar();
                scanf("%s",s);
                if(strcmp("QUERY",s)==0)
                {
                    int ind;
                    scanf("%d",&ind);

                    int t=str[ind]-'a';
                    if(l[t]==1)
                        printf("-1\n");
                    else
                        printf("%d\n",find(t,ind));
                }
                if(strcmp("INSERT",s)==0)
                {
                    scanf("%s",s);
                    t=s[0]-'a';
                    a[t][l[t]++]=len;
                    str[len]=s[0];
                    str[++len]='\0';
                }
            }
        }
    }
    return 0;
}



你可能感兴趣的:(hash)