题目大意
给出两个人对于 “ 昨天、今天、明天 ” 的描述,其中,每个人仅提供一个正确信息。确定 “ 今天 ” 到底是星期几,并给出两人的正确信息是哪个维度。
考场上用了比较笨的方法:枚举每个人的正确信息
十五分钟AC
#include
#include
#include
#include
using namespace std;
char day[7][20]={"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
char ans[3][20]={"yesterday","today","tomorrow"};
int a[5];
int b[5];
int main()
{
scanf("%d%d%d",&a[0],&a[1],&a[2]);
scanf("%d%d%d",&b[0],&b[1],&b[2]);
if (a[0]==b[0]) { //yes
printf("%s\n",day[(a[0]+1)%7]);
printf("%s\n%s",ans[0],ans[0]);
}
else if ((a[0]+1)%7==b[1]) { //yes to
printf("%s\n",day[b[1]]);
printf("%s\n%s",ans[0],ans[1]);
}
else if ((a[0]+2)%7==b[2]) { //yes mo
printf("%s\n",day[(a[0]+1)%7]);
printf("%s\n%s",ans[0],ans[2]);
}
else if (a[1]==(b[0]+1)%7) { //to yes
printf("%s\n",day[a[1]]);
printf("%s\n%s",ans[1],ans[0]);
}
else if (a[1]==b[1]) { //to
printf("%s\n",day[a[1]]);
printf("%s\n%s",ans[1],ans[1]);
}
else if ((a[1]+1)%7==b[2]) { //to mo
printf("%s\n",day[a[1]]);
printf("%s\n%s",ans[1],ans[2]);
}
else if (a[2]==(b[0]+2)%7) { //mo yes
printf("%s\n",day[(b[0]+1)%7]);
printf("%s\n%s",ans[2],ans[0]);
}
else if (a[2]==(b[1]+1)%7) { //mo to
printf("%s\n",day[b[1]]);
printf("%s\n%s",ans[2],ans[1]);
}
else if (a[2]==b[2]) { //mo mo
printf("%s\n",day[(a[2]-1+7)%7]);
printf("%s\n%s",ans[2],ans[2]);
}
return 0;
}
题目大意
模拟操作系统中的LRU机制,即最近最少使用(Least Recently Used),选择最近最久未使用的页面予以替换。
数据范围允许我投机取巧,使用一个队列记录cache中的页
二十分钟AC
#include
#include
#include
using namespace std;
const int N=10010;
const int M=100010;
int p[N*2]={0};
int Q[M*2];
int tou=0;
int wei=0;
int sz=0;
int ans[M];
int cnt=0;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i) {
int x;
scanf("%d",&x);
if (!p[x]) { //not in cache
if (sz<n) {
++sz;
++tou;
p[x]=tou;
Q[tou]=x;
}
else {
while (Q[wei]==0) wei++;
ans[++cnt]=Q[wei]; //out
p[Q[wei]]=0;
++wei;
++tou;
p[x]=tou;
Q[tou]=x;
}
}
else {
Q[p[x]]=0;
++tou;
p[x]=tou;
Q[tou]=x;
}
}
for (int i=1;i<=cnt;++i) {
printf("%d",ans[i]);
if (i<cnt) printf(" ");
}
return 0;
}
题目大意
给出一个有向图,询问某序列是否能够通过dfs该图得到。注意,每个节点仅被遍历一次,非连通图中可以有多个dfs起点。
可以通过dfs得到的序列:
二十五分钟AC
#include
#include
#include
using namespace std;
const int N=1010;
const int M=10010;
int way[N][N]={0};
int n,m,k;
int a[N];
int init[N]={0};
int outit[N]={0};
int vis[N]={0};
int judge(int x,int y) {
if (outit[x] == 0) return 1;
for (int i=1;i<=n;++i) {
if (way[x][i] && !vis[i]) return 0;
}
return 1;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for (int i=1;i<=m;++i) {
int u,v;
scanf("%d%d",&u,&v);
way[u][v]=1;
init[v]++;
outit[u]++;
}
for (int i=1;i<=k;++i) {
int flag=1;
for (int j=1;j<=n;++j) {
scanf("%d",&a[j]);
vis[j]=0;
}
vis[a[1]]=1;
for (int j=2;j<=n;++j) {
int x=a[j];
if (vis[x]) {
flag=0;
break;
}
if (!way[a[j-1]][x] && !judge(a[j-1],x)) {
flag=0;
break;
}
vis[x]=1;
}
if (flag==0) {
printf("no\n");
}
else {
printf("yes\n");
}
}
return 0;
}
题目大意
有一棵完全d叉树,给出前序遍历,构造该树的层次遍历和父子关系。
按照层次遍历给每个节点编号后
完全二叉树存在这样的性质:对于任一节点 x x x, 2 ∗ x 2*x 2∗x为其左儿子( 2 ∗ x < = n 2*x<=n 2∗x<=n), 2 ∗ x + 1 2*x+1 2∗x+1为其右儿子( 2 ∗ x + 1 < = n 2*x+1<=n 2∗x+1<=n)
同理,完全d叉树存在类似性质:对于任一节点 x x x, d ∗ x − ( d − 2 ) d*x-(d-2) d∗x−(d−2)到 d ∗ x + 1 d*x+1 d∗x+1为其所有的儿子(儿子的编号 < = n <=n <=n)
前序遍历采取 “ 先根后儿子 ” 的遍历顺序
这就是赤裸裸的 “ 父子 ” 关系
我们可以根据之前得到的结论,对于每个节点重新赋予层次遍历的编号
从前往后扫描前序遍历,构造完全d叉树
思路比较精妙,可以直接看代码
三十分钟AC
#include
#include
#include
using namespace std;
const int N=60;
struct node{
int fa;
int num;
};
node T[N];
int n,d,k;
int pre[N];
int deep[N];
int cnt=0;
void build(int f,int id) {
T[id].num=pre[++cnt];
T[id].fa=f;
for (int i=id*d-(d-2);i<=id*d+1;++i) {
if (i<=n) {
build(id,i);
}
else break;
}
}
int main()
{
scanf("%d%d",&n,&d);
for (int i=1;i<=n;++i) {
scanf("%d",&pre[i]);
}
build(0,1);
for (int i=1;i<=n;++i) {
printf("%d",T[i].num);
if (i<n) printf(" ");
}
printf("\n");
scanf("%d",&k);
for (int i=1;i<=k;++i) {
int x;
scanf("%d",&x);
x++;
while (x!=0) {
printf("%d",T[x].num);
if (x!=1) printf(" ");
else printf("\n");
x=T[x].fa;
}
}
return 0;
}