A. 日期
题目描述
请你计算出第 X 年 Y 月 Z 日是第X年的第几天。其中,1月1日是第一天,1月2日是第二天,以此类推。
计算时请注意闰年的影响。对于非整百年,年数能整除4是闰年,否则不是闰年;对于整百年,年数能整除400是闰年,否则不是闰年。如1900年和1901年不是闰年,而2000年和2004年是闰年。
输入格式
第一行有一个整数
T
(T≤100)
,表示一共有T组数据需要你处理。
接下来一共有T行,每行是一个如下格式的字符串:
X
:
Y
:
Z
,表示你需要计算第
X
年
Y
月
Z
日是第
X
年的第几天。其中
X
是一个大于0,小于2100的整数。保证字符串的格式都是合法的,字符串所表示的日期也都是存在的。
输出格式
对于每组数据,你需要输出一个整数,表示所求得的结果。
输入样例
2
2013:4:12
112:4:12
输出样例
102
103
#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);
}
}
}
B. 统计节点个数
题目描述
给出一棵有向树,一共有 N ( 1<N≤1000 )个节点,如果一个节点的度(入度+出度)不小于它所有儿子以及它父亲的度(如果存在父亲或儿子),那么我们称这个节点为p节点,现在你的任务是统计p节点的个数。
如样例,第一组的p节点为1,2,3;第二组的p节点为0。
输入格式
第一行为数据组数
T
(
1≤T≤100
)。
每组数据第一行为
N
表示树的节点数。后面为
N−1
行,每行两个数
x
,
y
(
0≤x,y<N
),代表
y
是
x
的儿子节点。
输出格式
每组数据输出一行,为一个整数,代表这棵树上p节点的个数。
输入样例
2
5
0 1
1 2
2 3
3 4
3
0 2
0 1
输出样例
3
1
#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
*/
C. 中序遍历序列
题目描述
给出一个序列,判断该序列是不是某二叉搜索树的中序遍历序列,如果是输出"Yes",否则输出"No"。
一颗带权二叉树是一颗二叉搜索树(二叉排序树),当且仅当对于任意一个节点,他的左子树中的所有权值小于当前节点的权值,且它的右子树中的所有权值均大于当前节点的权值。
输入格式
第一行
T
(T≤10)
代表数据组数。
每组数据包括两行:
第一行为一个整数
N
(1≤N ≤400)
,表示序列的长度。
第二行包含
N
个整数,表示这个这个序列,序列中的数的
x
范围为
(1≤x≤100000)
。
输出格式
每组数据,如果是二叉搜索树的中序遍历序列输出"Yes",否则输出"No"。
输入样例
2
4
1 2 3 4
4
1 3 2 4
输出样例
Yes
No
#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
*/
D. 最小距离查询
题目描述
给定一个由小写字母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
(
T≤20
),表示测试数据的组数。
每组输入数据的第一行是一个初始串S。第二行是一个正整数
m
(
1≤m≤100000
),表示总共操作的数量。接下来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
#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;
}