团体程序设计天梯赛-L2组

--------------------------------------------------------------------------------

题目传送门

团体程序设计天梯赛-L2组
--------------------------------------------------------------------------------
更多详见>>

OJ题解系列 目录导航帖
--------------------------------------------------------------------------------

这里是团体程序设计天梯赛-L2组
团体程序设计天梯赛,简称CCCC竞赛,从总体上来看,该竞赛难度不大,掌握基础的数据结构和算法便能够取得不错的分数,L1/L2/L3按照难度递增的顺序排列,其中L1是入门级的难度,类似于PAT乙级考试前3题,占100分;L2级加入了数据结构的元素,难度和PAT乙级后2题/PAT甲级前3题难度相当,占75分,L3级加入了算法进阶的内容,难度和PAT甲级最后一题/PAT顶级的难度一致,占75分。因此,练习的时候也可参考PAT专题部分,具体内容详见
OJ题解系列 目录导航帖
接下来就是题解部分了,每道算法题都标注有对应的算法标签,对于那些易错、较难或是测试点比较特殊的题目会着重标注,本章推荐的题目有:

L2-012 关于堆的判断 (25 分) 堆 + 字符串
L2-013 红色警报 (25 分) 并查集
L2-014 列车调度 (25 分) 单调队列
L2-016 愿天下有情人都是失散多年的兄妹 (25 分)
L2-030 冰岛人 (25 分)
并查集 + DFS/BFS
L2-018 多项式A除以B (25 分) 高精
L2-028 秀恩爱分得快 (25 分) 字符串 + 枚举
L2-034 口罩发放 (25 分) 大模拟 + 排序
L2-035 完全二叉树的层序遍历 (25 分) 树,二叉树 + 遍历

--------------------------------------------------------------------------------

L2-001 紧急救援 (25 分)

算法标签: 图论 + dijkstra + dfs
注意: dijkstra跑最短路,同时统计路径数,并更新点权最大值,是一道标准模板题,具体详见数据结构专题系列-图论

#include<bits/stdc++.h>
using namespace std;
int N,M,S,D;
const int maxn = 505;
int dp[maxn];
int num[maxn];
int pre[maxn];
int weight[maxn];
bool vis[maxn];
int a[maxn];
struct node{int v;int w;
};
node temp;
vector<node> G[maxn];
void Dijkstra(int S){memset(vis,0,sizeof(vis));memset(dp,0x3f,sizeof(dp));memset(num,0,sizeof(num));memset(weight,0,sizeof(weight));dp[S] = 0;num[S] = 1;weight[S] = a[S];priority_queue<pair<int,int> > q;q.push(make_pair(-dp[S],S));while(!q.empty()){pair<int,int> f = q.top();q.pop();int u = f.second;if(vis[u]){continue;}vis[u] = true;for(int i=0;i<G[u].size();i++){int v = G[u][i].v;int w = G[u][i].w;if(!vis[v]){if(dp[u]+w<dp[v]){dp[v] = dp[u] + w;num[v] = num[u];weight[v] = weight[u] + a[v];pre[v] = u;q.push(make_pair(-dp[v],v));}else if(dp[u]+w==dp[v]){num[v] += num[u];if(weight[u]+a[v]>weight[v]){weight[v] = weight[u] + a[v];pre[v] = u;}}}}}
}
vector<int> ans;
void Dfs(int u){if(u == S){ans.push_back(u);return;}Dfs(pre[u]);ans.push_back(u);
}
int main(){cin >> N >> M >> S >> D; for(int i=0;i<N;i++){cin >> a[i];} for(int i=1;i<=M;i++){int u,v,w;cin >> u >> v >> w;temp.v = v;temp.w = w;G[u].push_back(temp);temp.v = u;G[v].push_back(temp);}Dijkstra(S);cout << num[D] << " " << weight[D] << endl;Dfs(D);for(int i=0;i<ans.size();i++){if(i==0){printf("%d",ans[i]);}else{printf(" %d",ans[i]);} }return 0;
} 

L2-002 链表去重 (25 分)

算法标签: 模拟 + 链表

#include<bits/stdc++.h>
using namespace std;
struct node{int value;int next;
};
const int maxn = 1e5+5;
node n[maxn];int ori_add[maxn];
int ori_value[maxn];
int post_add[maxn];
int post_value[maxn];
int cnt1 = 0;
int cnt2 = 0;
set<int> s;int main(){int start;int N;cin >> start >> N;for(int i=0;i<N;i++){int y;scanf("%d",&y);scanf("%d%d",&n[y].value,&n[y].next);}while(start!=-1){if(s.find(abs(n[start].value))!=s.end()){post_add[cnt2] = start;post_value[cnt2] = n[start].value;cnt2++; }else{ori_add[cnt1] = start;ori_value[cnt1] = n[start].value;s.insert(abs(n[start].value));cnt1++;}start = n[start].next;} for(int i=0;i<cnt1;i++){if(i!=cnt1-1){printf("%05d %d %05d\n",ori_add[i],ori_value[i],ori_add[i+1]);}else{printf("%05d %d -1\n",ori_add[i],ori_value[i]);}}for(int i=0;i<cnt2;i++){if(i!=cnt2-1){printf("%05d %d %05d\n",post_add[i],post_value[i],post_add[i+1]);}else{printf("%05d %d -1\n",post_add[i],post_value[i],post_add[i+1]);}}return 0;
} 

L2-003 月饼 (25 分)

算法标签: 完全背包的简单版

#include<bits/stdc++.h>
using namespace std;
int N,D;
int maxn = 1005;
typedef struct mooncake{double num;double price;double singleprice;
}mooncake;
bool cmp(mooncake m1,mooncake m2){return m1.singleprice > m2.singleprice;
}
int main(){cin >> N >> D;mooncake m[N];for(int i=0;i<N;i++){cin >> m[i].num;}for(int i=0;i<N;i++){cin >> m[i].price;}for(int i=0;i<N;i++){m[i].singleprice = (m[i].price * 1.0) /(m[i].num * 1.0);}sort(m,m+N,cmp);int site = 0;double totalprice = 0.0;while(D!=0){if(m[site].num <= D){D -= m[site].num;totalprice = totalprice + m[site].price;}else{totalprice = totalprice + m[site].singleprice * D;D = 0;}site++;}printf("%.2lf\n",totalprice);return 0;
}

L2-004 这是二叉搜索树吗? (25 分)

算法标签: 树,二叉树 + 遍历
注意: 所谓的镜像树,其实就是指颠倒了左右子树的访问顺序,其它条件都不变,因此,本题实质上依然是考察建树+遍历

#include<bits/stdc++.h>
using namespace std;vector<int> pre,preM,post,postM,origin;int N;
struct node{int data;node* lchild;node* rchild;
};node* root = NULL;void insert(node* &root,int x){if(root==NULL){node *Node = new node;Node->data = x;Node->lchild = NULL;Node->rchild = NULL;root = Node;return;}if(x<root->data){insert(root->lchild,x);}else{insert(root->rchild,x);}
}int cnt = 0;void PreOrder(node* root,vector<int> &pre){if(root==NULL){return;}pre.push_back(root->data);PreOrder(root->lchild,pre);PreOrder(root->rchild,pre);
}void MirrorOrder(node *root,vector<int> &preM){if(root==NULL){return;}preM.push_back(root->data);MirrorOrder(root->rchild,preM);MirrorOrder(root->lchild,preM);
}void PostOrder(node* root,vector<int> &post){if(root==NULL){return;}PostOrder(root->lchild,post);PostOrder(root->rchild,post);post.push_back(root->data);
}void PostOrder1(node* root,vector<int> &postM){if(root==NULL){return;}PostOrder1(root->rchild,postM);PostOrder1(root->lchild,postM);postM.push_back(root->data);
}int main(){cin >> N;for(int i=0;i<N;i++){int t;cin >> t;origin.push_back(t);insert(root,t);}PreOrder(root,pre);MirrorOrder(root,preM);if(pre==origin){printf("YES\n");PostOrder(root,post);for(int i=0;i<post.size();i++){if(i==0){printf("%d",post[i]);}else{printf(" %d",post[i]);}}}else if(preM==origin){printf("YES\n");PostOrder1(root,postM);for(int i=0;i<postM.size();i++){if(i==0){printf("%d",postM[i]);}else{printf(" %d",postM[i]);}}}else{printf("NO\n");}return 0;
}

L2-005 集合相似度 (25 分)

算法标签: 集合
注意: 本题考察的重点是集合,由于集合中的元素不能重复,因此,可用STL的set进行操作,每次查询输入两个集合的编号,我们采用枚举法判断集合的相似度,最后保留2位小数后输出

#include<bits/stdc++.h>
using namespace std;
set<int> a[55];
double query[60][60];
int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){int M;scanf("%d",&M);for(int j=0;j<M;j++){int t;scanf("%d",&t);a[i].insert(t);}}int K;scanf("%d",&K);for(int i=0;i<K;i++){int g,h;scanf("%d%d",&g,&h);set<int>::iterator it1;set<int>::iterator it2;int Nc = 0;for(it1 = a[g].begin(),it2 = a[h].begin();it1!=a[g].end() && it2!=a[h].end();){if(*it1 == *it2){Nc++;it1++;it2++;}else if(*it1<*it2){it1++;}else{it2++;}}int Nn = a[g].size() + a[h].size() - Nc;double r = (Nc * 1.0) /(Nn * 1.0);printf("%.2lf%%\n",r*100.0);}return 0;
} 

L2-006 树的遍历 (25 分)

算法标签: 树,二叉树 + 遍历
注意: 首先输入中序遍历和后序遍历,建立一棵树,然后从根结点出发,进行层次遍历

#include<bits/stdc++.h>
using namespace std;int post[35];
int in[35];
struct node{int data;node* lchild;node* rchild;
};
node* root = NULL;
node* newnode(int v){node* Node = new node;Node->data = v;Node->lchild = NULL;Node->rchild = NULL; return Node;
}
node* Create(int inL,int inR,int postL,int postR){if(postL>postR){return NULL;}int d = post[postR];int k;for(int i=inL;i<=inR;i++){if(in[i]==d){k = i;break;}}int numleft = k-inL;node* Node = new node;Node->data = d; Node->lchild = Create(inL,k-1,postL,postL+numleft-1);Node->rchild = Create(k+1,inR,postL+numleft,postR-1); return Node;
}
queue<node*> q;
int n;
void Level(node* root){int T = n;q.push(root);while(!q.empty()){node* f = q.front();q.pop();if(T==1){printf("%d\n",f->data);}else{printf("%d ",f->data);}T--;if(f->lchild){q.push(f->lchild);}if(f->rchild){q.push(f->rchild);}}
}
int main(){cin >> n;for(int i=0;i<n;i++){cin >> post[i];} for(int i=0;i<n;i++){cin >> in[i];}root = Create(0,n-1,0,n-1);Level(root);return 0;
}

L2-007 家庭房产 (25 分)

算法标签: 并查集 + 排序
注意: 本题极易与树、二叉树知识点混淆,该题的正确解法是并查集操作,合并parent与child,然后划定area

#include<bits/stdc++.h>
using namespace std;
struct person{int father;int mother;vector<int> child;int Mstate;int Area;bool f = false;
};
person p[10005];int father[10005];int findfather(int x){if(x == father[x]){return x;}else{int F = findfather(father[x]);father[x] = F;return F; }
}void Union(int a,int b){int fa = findfather(a);int fb = findfather(b);if(fa!=fb){if(fa<fb){father[fb] = fa;}else{father[fa] = fb;  }}
}int num[10005];
double area[10005];
double state[10005];struct ans{int ID;int number;double state;double area;
};
ans a[10005];bool vis[10005];
bool hashT[10005];int cnt = 0;bool cmp(ans a1,ans a2){if(a1.area!=a2.area){return a1.area > a2.area;}else{return a1.ID < a2.ID; }
}int main(){for(int i=0;i<=9999;i++){father[i] = i;}int N;scanf("%d",&N);for(int i=0;i<N;i++){int id;scanf("%d",&id);hashT[id] = true;scanf("%d%d",&p[id].father,&p[id].mother);if(p[id].father!=-1){hashT[p[id].father] = true;Union(id,p[id].father);}if(p[id].mother!=-1){hashT[p[id].mother] = true;Union(id,p[id].mother);}int k;scanf("%d",&k);for(int j=0;j<k;j++){int cid;scanf("%d",&cid);p[id].child.push_back(cid);hashT[cid] = true;Union(id,cid);}scanf("%d%d",&p[id].Mstate,&p[id].Area);p[id].f = true;}for(int i=0;i<=9999;i++){int F = findfather(i);num[F]++;if(p[i].f){area[F] += p[i].Area;state[F] += p[i].Mstate;}}for(int i=0;i<=9999;i++){if(hashT[i]){int F = findfather(i);if(!vis[F] && num[F]){vis[F] = true;a[cnt].ID = i;a[cnt].number = num[F];a[cnt].state = state[F]/(num[F]*1.0);a[cnt].area = area[F]/(num[F]*1.0);cnt++;}   }}sort(a,a+cnt,cmp);printf("%d\n",cnt);for(int i=0;i<cnt;i++){printf("%04d %d %.3lf %.3lf\n",a[i].ID,a[i].number,a[i].state,a[i].area);}return 0;
} 

L2-008 最长对称子串 (25 分)

算法标签: DP
注意点: 动态规划求最长回文子串的题目,可得初始条件如下:
设dp[i][j]dp[i][j]dp[i][j]表示从第i个字符到第j个字符为回文串,那么
dp[i][i]=1,L=1dp[i][i]=1,L=1dp[i][i]=1,L=1
dp[i][i+1]=1,s[i]==s[i+1],L=2dp[i][i+1]=1,s[i]==s[i+1],L=2dp[i][i+1]=1,s[i]==s[i+1],L=2
dp[i][j]=1,dp[i+1][j−1]=1且s[i]==s[j],L>=3dp[i][j]=1,dp[i+1][j-1]=1且s[i]==s[j],L>=3dp[i][j]=1,dp[i+1][j−1]=1且s[i]==s[j],L>=3

#include<bits/stdc++.h>
using namespace std;
int dp[1005][1005];int main(){string s;getline(cin,s);int len = s.size();int ans = 1;for(int i=0;i<len;i++){dp[i][i] = 1;if(i>=1 && s[i-1]==s[i]){dp[i-1][i] = 1;ans = 2;}}for(int i=3;i<=len;i++){for(int j=0;j<len-i+1;j++){int k = j+i-1;if(s[k] == s[j] && dp[j+1][k-1]==1){dp[j][k] = 1;ans = i;}}}cout << ans << endl;return 0;
}

L2-009 抢红包 (25 分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
struct node{double price = 0.0;int num = 0;int number;
};
const int maxn = 1e4+5;
node stu[maxn];
bool cmp(node stu1,node stu2){if(fabs(stu1.price-stu2.price)>1e-3){return stu1.price>stu2.price;}else if(stu1.num!=stu2.num){return stu1.num>stu2.num;}else{return stu1.number<stu2.number;}
}
int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){stu[i].number = i;int K;scanf("%d",&K);for(int j=1;j<=K;j++){int id,v;scanf("%d%d",&id,&v);stu[i].price -= (v/100.0);stu[id].price += (v/100.0);stu[id].num++;}}sort(stu+1,stu+N+1,cmp);for(int i=1;i<=N;i++){printf("%d %.2lf\n",stu[i].number,stu[i].price);}return 0;
}

L2-010 排座位 (25 分)

算法标签: 并查集

#include<bits/stdc++.h>
using namespace std;
int N,M,K;
int father[105];
int findfather(int x){if(x==father[x]){return x;}else{int F = findfather(father[x]);father[x] = F;return F; }
}
void Union(int a,int b){int fA = findfather(a);int fB = findfather(b);if(fA!=fB){father[fA] = fB;}
}set<int> s2[105];
int main(){scanf("%d%d%d",&N,&M,&K);for(int i=1;i<=N;i++){father[i] = i;}for(int i=1;i<=M;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(w==1){Union(u,v);}else{s2[u].insert(v);s2[v].insert(u);}}for(int i=1;i<=K;i++){int u,v;scanf("%d%d",&u,&v);int fu = findfather(u);int fv = findfather(v);if(fu==fv && s2[u].find(v)==s2[u].end()){printf("No problem\n");}else if(fu!=fv && s2[u].find(v)==s2[u].end()){printf("OK\n");}else{if(fu!=fv && s2[u].find(v)!=s2[u].end()){printf("No way\n");}else{printf("OK but...\n");}}}return 0;
}

L2-011 玩转二叉树 (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 根据中序遍历和先序遍历建树,然后层序遍历即可

#include<bits/stdc++.h>
using namespace std;
int in[35];
int pre[35];struct node{int data;node* lchild;node* rchild;
};node* newnode(int v){node* Node = new node;Node->data = v;Node->lchild = NULL;Node->rchild = NULL;return Node;
}node* Create(int preL,int preR,int inL,int inR){if(preL>preR){return NULL;}node* root = newnode(pre[preL]);int k;for(int i=inL;i<=inR;i++){if(pre[preL] == in[i]){k = i;break;}}int numleft = k-inL;root->lchild = Create(preL+1,preL+numleft,inL,inL+numleft-1);root->rchild = Create(preL+numleft+1,preR,inL+numleft+1,inR);return root;
}
void levelorder(node* root){queue<node*> q;q.push(root);bool f1 = true;while(!q.empty()){node* f = q.front();q.pop();if(f1){cout << f->data;f1 = false;}else{cout << " " << f->data;}if(f->rchild){q.push(f->rchild);}if(f->lchild){q.push(f->lchild);}}
}
int main(){int n;cin >> n;for(int i=0;i<n;i++){cin >> in[i];}for(int i=0;i<n;i++){cin >> pre[i];}node* root = NULL;root = Create(0,n-1,0,n-1);levelorder(root);return 0;
}

L2-012 关于堆的判断 (25 分)

算法标签: 堆 + 字符串
注意点: 本题考察堆的插入操作:
1.本题容易与Floyd建堆混淆,题目中明确要求逐个元素插入到堆中,因此,是采用自下而上的上滤算法建堆,而不是采用自下而上的下滤算法建堆
2.如何判断这四类操作
(1)根结点很显然,判断a[1]是否与输入的root相等
(2)判断兄弟结点,拥有共同的父节点,判断n1/2 == n2/2
(3)判断父节点,n2/2 == n1
(4)判断子节点,n1/2 == n2
3.字符串中数字的读入,这里有一个坑点,负数如-1003,需特判前面的负号[测试点1]/[测试点3]

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
int a[maxn];
void downadjust(int N){while(N>=2){if(a[N]<a[N/2]){swap(a[N],a[N/2]);}else{break;}N/=2;}
}
int main(){int N,M;cin >> N >> M;for(int i=1;i<=N;i++){cin >> a[i];downadjust(i);}getchar();for(int i=1;i<=M;i++){string s;getline(cin,s);if(s.find("is the root")!=-1){int site = s.find(" is the root");int num = 0;if(s[0] == '-'){for(int i=1;i<site;i++){num = num*10 + s[i] - '0';}num = -num;}else{for(int i=0;i<site;i++){num = num*10 + s[i] - '0';}   }if(a[1] == num){printf("T\n");}else{printf("F\n");}}else if(s.find("are siblings")!=-1){int site1 = s.find(" and");int num1 = 0;if(s[0] == '-'){for(int i=1;i<site1;i++){num1 = num1*10 + s[i] - '0';}num1 = -num1;}else{for(int i=0;i<site1;i++){num1 = num1*10 + s[i] - '0';}  }int site2 = s.find("and ");int site3 = s.find(" are");int num2 = 0;if(s[site2+4] == '-'){for(int i=site2+5;i<site3;i++){num2 = num2*10 + s[i] - '0';}num2 = -num2;}else{for(int i=site2+4;i<site3;i++){num2 = num2*10 + s[i] - '0';}    }int ans1,ans2;for(int i=1;i<=N;i++){if(num1 == a[i]){ans1 = i;break;}}for(int i=1;i<=N;i++){if(num2 == a[i]){ans2 = i;break;}}if(ans1/2 == ans2/2){printf("T\n");}else{printf("F\n");}}else if(s.find("is the parent of")!=-1){int site1 = s.find(" is");int num1 = 0;if(s[0] == '-'){for(int i=1;i<site1;i++){num1 = num1*10 + s[i] - '0';}num1 = -num1;}else{for(int i=0;i<site1;i++){num1 = num1*10 + s[i] - '0';}    }int site2 = s.find("of ");int num2 = 0;if(s[site2+3] == '-'){for(int i=site2+4;i<s.size();i++){num2 = num2*10 + s[i] - '0';}num2 = -num2;}else{for(int i=site2+3;i<s.size();i++){num2 = num2*10 + s[i] - '0';} }int ans1,ans2;for(int i=1;i<=N;i++){if(num1 == a[i]){ans1 = i;break;}}for(int i=1;i<=N;i++){if(num2 == a[i]){ans2 = i;break;}}if(ans2/2==ans1){printf("T\n");}else{printf("F\n");}}else{int site1 = s.find(" is");int num1 = 0;if(s[0] == '-'){for(int i=1;i<site1;i++){num1 = num1*10 + s[i] - '0';}num1 = -num1;}else{for(int i=0;i<site1;i++){num1 = num1*10 + s[i] - '0';}}int site2 = s.find("of ");int num2 = 0;if(s[site2+3] == '-'){for(int i=site2+4;i<s.size();i++){num2 = num2*10 + s[i] - '0';}num2 = -num2;}else{for(int i=site2+3;i<s.size();i++){num2 = num2*10 + s[i] - '0';}   }int ans1,ans2;for(int i=1;i<=N;i++){if(num1 == a[i]){ans1 = i;break;}}for(int i=1;i<=N;i++){if(num2 == a[i]){ans2 = i;break;}}if(ans1/2==ans2){printf("T\n"); }else{printf("F\n");}}}return 0;
}

L2-013 红色警报 (25 分)

算法标签: 并查集
注意点: 本题考察的算法是并查集,但考察的是并查集的一种变式:如何理解题目所给的条件(失去一个城市并不改变其他城市之间的连通性)
首先我们来分析一下这个条件:
(1)若失去一个城市之后。连通图数量减少了1:那么失去的城市本身就是一个连通分量,它并不影响其他城市的连通性
(2)若失去一个城市之后,连通图数量不变:此时意味着本来是若干个连通分量,删除结点后,仍然是若干个连通分量,这些连通分量中的城市互相可达,说明删除这个城市并不影响其他城市的连通性
(3)若失去一个城市之后,连通图数量增加了1:此时意味着多出来的连通分量必定是原连通分量裂开后形成的,此时破坏了其余城市之间的连通性,因此这种情况下会发出alert

#include<bits/stdc++.h>
using namespace std;
const int maxn = 505;
bool hashT[maxn];
vector<int> G[maxn];
int a[maxn];
int father[maxn];
vector<int> res;
int findfather(int x){if(x==father[x]){return x;}else{int F = findfather(father[x]);father[x] = F;return F; }
}
void Union(int a,int b){int fA = findfather(a);int fB = findfather(b);if(fA!=fB){father[fA] = fB;}
}
int calcu(int N){set<int> s;for(int i=0;i<N;i++){father[i] = i;}for(int i=0;i<N;i++){if(!hashT[i]){for(int j=0;j<G[i].size();j++){int v = G[i][j];if(!hashT[v]){Union(i,v);}} }}for(int i=0;i<N;i++){if(!hashT[i]){s.insert(findfather(i));}} int ans = s.size();return ans;
}
int main(){int N,M;cin >> N >> M;for(int i=1;i<=M;i++){int u,v;cin >> u >> v;G[u].push_back(v);G[v].push_back(u); }int K;cin >> K;for(int i=1;i<=K;i++){cin >> a[i];} int start = calcu(N);for(int i=1;i<=K;i++){hashT[a[i]] = true;int tmp = calcu(N);if(tmp<=start){printf("City %d is lost.\n",a[i]);}else{printf("Red Alert: City %d is lost!\n",a[i]);}start = tmp;}if(K==N){printf("Game Over.\n");}return 0;
}

L2-014 列车调度 (25 分)

算法标签: 单调队列
注意点: 一道好题!这道题思维难度比较大,但是代码量相对较少
首先我们分析一下题目,题目中要求火车出站的序列是单调递减的,也就是说编号较大的火车应该停靠在站台的前端,而编号较小的火车应该停靠在站台的后端,等到编号大的火车出站之后,编号小的自然排在了队头,这样即可满足出站的要求
仔细回想一下所学过的数据结构,发现单调队列正好满足这个要求,队列中总是保存着较小的编号,因此第一种方法就形成了,建立若干个单调队列,每个队列记录最小的编号,然后每次新来的火车,通过二分查找,找到最小编号最接近的站台,排在其后面,并更新该单调队列的记录,此方法可行,但还有更好的方案
纵观上一个方法,尽管我们需要维护若干个单调队列,但是,单调队列无需保存所有火车的编号,而只需要保存其中序列最小的那个即可,因此,可把每个队列抽象成一个数,这个数代表了能够进站的火车最大编号,所有小于这个数的火车被允许进站,排在其位置之后,并更新编号,编号的变化具有单调性(递减),而二分查找可替换成平衡树上查找,因此,我们引入一个集合set,用lower_bound二分查找,用insert快速插入,效率最高!

#include<bits/stdc++.h>
using namespace std;
set<int> s;
int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){int t;scanf("%d",&t);set<int>::iterator it;it = s.lower_bound(t);if(it!=s.end()){s.erase(it);s.insert(t);}else{s.insert(t);}}int ans = s.size();cout << ans << endl;return 0;
}

L2-015 互评成绩 (25 分)

算法标签: 排序
注意点: 先对每个人的部分成绩进行排序,然后去掉最高分和最低分,取平均值计算,得到个人最终成绩,最后对所有人的成绩进行排序,输出前M个即可

#include<bits/stdc++.h>
using namespace std;
double ans[10005];
int a[15];
int main(){int N,K,M;scanf("%d%d%d",&N,&K,&M);for(int i=1;i<=N;i++){for(int j=1;j<=K;j++){scanf("%d",&a[j]);} sort(a+1,a+1+K);double ave = 0.0;for(int j=2;j<=K-1;j++){ave += a[j];}ave /= (K-2);ans[i] = ave;}sort(ans+1,ans+1+N);for(int i=N-M+1;i<=N;i++){if(i!=N){printf("%.3lf ",ans[i]);}else{printf("%.3lf\n",ans[i]);}}return 0;
}

L2-016 愿天下有情人都是失散多年的兄妹 (25 分)

算法标签: 并查集 + BFS/DFS
注意点: 首先,考虑到这道题的数据结构不是一棵树,因为找不到公共的祖先源点(根结点不唯一,是森林),因此采用并查集将所有祖先关系都合并起来(祖先关系不同源的人无需判断5层)
接着,有K组输入(题目中未给出K的大小,实际测试结果来看,大约100组数据左右,因为若K很大,BFS/DFS都是超时的算法,需考虑倍增LCA),每组输入给出2个编号,首先判断2个编号的性别,如果一样,输出Never Mind,否则再判断是否同源,若不是,则输出Yes,若是,继续判断5代以内是否有交集,由于题目中说了,给的数据都是同辈份的,这里就省略了需将结点提升到同一层的步骤(倍增LCA),可直接将ID1编号用BFS算法遍历5个层次,把每个层次遍历过的结点都打上已访问的标签,再进行ID2编号,若在5个层次内访问到了已打过标签的结点,则输出No,否则输出Yes

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int hashT[maxn];
int father[maxn];
vector<int> G[maxn];
bool vis[maxn];int findfather(int x){if(x==father[x]){return x;}else{int F = findfather(father[x]);father[x] = F;return F;  }
}
void Union(int a,int b){int fA = findfather(a);int fB = findfather(b);if(fA!=fB){father[fA] = fB;}
}
void BFS(int u){queue<pair<int,int> > q;q.push(make_pair(u,1));vis[u] = true;while(!q.empty()){pair<int,int> f = q.front();q.pop();int u = f.first;int layer = f.second;if(layer<5){for(int i=0;i<G[u].size();i++){int v = G[u][i];if(!vis[v]){vis[v] = true;q.push(make_pair(v,layer+1));}}}}
}
int Check(int u){queue<pair<int,int> > q;q.push(make_pair(u,1));vis[u] = true;while(!q.empty()){pair<int,int> f = q.front();q.pop(); int u = f.first;int layer = f.second;if(layer<5){for(int i=0;i<G[u].size();i++){int v = G[u][i];if(!vis[v]){vis[v] = true;q.push(make_pair(v,layer+1));}else{return 0;} }}}return 1;
}
int main(){for(int i=0;i<maxn;i++){father[i] = i;}int n;scanf("%d",&n);for(int i=1;i<=n;i++){int id;scanf("%d",&id);char sex;cin >> sex;if(sex == 'M'){hashT[id] = 1;}else{hashT[id] = 2;}int mid,fid;scanf("%d%d",&fid,&mid);if(fid!=-1){G[id].push_back(fid);Union(id,fid);hashT[fid] = 1;}if(mid!=-1){G[id].push_back(mid);Union(id,mid);hashT[mid] = 2;}}int K;scanf("%d",&K);for(int i=1;i<=K;i++){int id1,id2;scanf("%d%d",&id1,&id2);if(hashT[id1] == hashT[id2]){printf("Never Mind\n"); }else{int f1 = findfather(id1);int f2 = findfather(id2);if(f1 == f2){memset(vis,0,sizeof(vis));BFS(id1);int f = Check(id2);if(f == 1){printf("Yes\n");}else{printf("No\n");}}else{printf("Yes\n");}    }}return 0;
}

L2-017 人以群分 (25 分)

算法标签: 排序
注意点: 先对输入的序列进行排序,然后划分前N/2个为内向型集合,后N-N/2个为外向型集合,两个集合之差即为Diff

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int a[maxn];
int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){scanf("%d",&a[i]);}sort(a+1,a+N+1);int N1,N2;if(N%2){N1 = N/2 +1 ;N2 = N-N1;}else{N1 = N2 = N/2;}printf("Outgoing #: %d\n",N1);printf("Introverted #: %d\n",N2);int ans = 0;for(int i=N-N1+1;i<=N;i++){ans += a[i];}for(int i=1;i<=N2;i++){ans -= a[i];}printf("Diff = %d\n",ans);return 0;
}

L2-018 多项式A除以B (25 分)

算法标签: 高精
注意点: 本题的算法和高精除法一致,模拟竖式相除即可,坑点有如下几个:
(1)本题未标注数据范围,题目保证所有指数是各不相同的非负整数,所有系数是非零整数,所有整数在整型范围内。
这句话本身是有问题的,如果指数e无限大(int上界),无法存储多项式(空间溢出),如果系数无限大,每一轮乘除过后误差不断累积,最终会使得15位有效数字的double不再精确,当误差超过0.05时,那么也无法完成多项式相除的功能(输出结果错误)
事实上,本题的数据比较水,最大的数据指数<3000,项数<3000,因此,除法最多3000次就能完成,算法复杂度O(n2)O(n^2)O(n2)即可
(2)零多项式是一个特殊多项式,对应输出为0 0 0.0,这个条件必须特判,测试点1/3/4会出现商或者余数是零多项式的情况
(3)舍入是什么:题目中说,多项式其实有常数项-1/27,但因其舍入后为0.0,这个例子还不够特殊,我们看输出样例:
3 2 0.3 1 0.2 0 -1.0,即
0.3x2+0.2x−1.00.3x^2+0.2x-1.00.3x2+0.2x−1.0
我们用竖式除法计算得到,商是13x2+29x−2627\frac{1}{3}x^2+\frac{2}{9}x-\frac{26}{27}31​x2+92​x−2726​
−2627=−0.96-\frac{26}{27}=-0.96−2726​=−0.96,答案输出为-1.0,这里就解释的很清楚了,舍入指的是对于小数点后1位进行四舍五入,因此用%.1lf的截断肯定错误,那么如何舍入呢?这里采用的是先将其扩大10倍,取整,四舍五入后,再除以10,还原成小数,对应于下面的convert函数

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e3+5;
double a[maxn];
double b[maxn];
double c[maxn];
double convert(double s){s *= 10;int res = (round)(s);double ans = res*1.0/10.0;return ans;
}
int main(){int N;scanf("%d",&N);int max1 = -1;int max2 = -1;for(int i=1;i<=N;i++){int e,coff;scanf("%d%d",&e,&coff);a[e] = coff*1.0;max1 = max(max1,e);} scanf("%d",&N);for(int i=1;i<=N;i++){int e,coff;scanf("%d%d",&e,&coff);b[e] = coff*1.0;max2 = max(max2,e);}for(int i=max1;i>=max2;i--){if(fabs(a[i])>1e-3){double t = a[i]/b[max2];c[i-max2] += t;for(int j=max2;j>=0;j--){if(fabs(b[j])>1e-3){a[i-max2+j] -= (t*b[j]);}}}}int ans1 = 0;for(int i=max1-max2;i>=0;i--){double t = convert(c[i]);if(fabs(t)>1e-2){ans1++;}}printf("%d",ans1);if(ans1){for(int i=max1-max2;i>=0;i--){double t = convert(c[i]);if(fabs(t)>1e-2){printf(" %d %.1lf",i,t);} }  }else{printf(" 0 0.0");}printf("\n");int ans2 = 0;for(int i=max2-1;i>=0;i--){double t = convert(a[i]);if(fabs(t)>1e-2){ans2++;}}printf("%d",ans2);if(ans2){for(int i=max2-1;i>=0;i--){double t = convert(a[i]);if(fabs(t)>1e-2){printf(" %d %.1lf",i,t);}} }else{printf(" 0 0.0");}return 0;
}

L2-019 悄悄关注 (25 分)

算法标签: 哈希
注意点: 先建立一个集合用于查询输入的名字,然后计算平均值,线性扫描并统计后按字典序排序输出

#include<bits/stdc++.h>
using namespace std;
set<string> s;
struct node{string name;int v;
};
node stu[10005];
string ans[10005];
int main(){int N;cin >> N;for(int i=1;i<=N;i++){string t;cin >> t;s.insert(t);}int M;cin >> M;double ave = 0.0;for(int i=1;i<=M;i++){cin >> stu[i].name >> stu[i].v;ave += stu[i].v;}ave /= M;int cnt = 0;for(int i=1;i<=M;i++){if(stu[i].v>ave && s.find(stu[i].name)==s.end()){ans[cnt++] = stu[i].name;}}sort(ans,ans+cnt);if(!cnt){cout << "Bing Mei You"  << endl;}else{for(int i=0;i<cnt;i++){cout << ans[i] << endl;}}return 0;
}

L2-020 功夫传人 (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 本题考察树的层次遍历,需注意测试点1的特殊情况,即祖师爷也是得道者,初始化的功力应该加倍!

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> G[maxn];
int hashT[maxn];
bool vis[maxn];
int N;
double Z,r;
double ans = 0.0;
void levelorder(int S){queue<pair<int,double>> q;if(hashT[S]){q.push(make_pair(S,Z*hashT[S]));}else{q.push(make_pair(S,Z));}vis[S] = true;while(!q.empty()){pair<int,double> f = q.front();q.pop();int u = f.first;double value = f.second;if(hashT[u]){ans += value;}for(int i=0;i<G[u].size();i++){int v = G[u][i];if(!vis[v]){if(hashT[v]){double temp = (100.0-r)/100.0 * value;temp = 1.0*temp*hashT[v];q.push(make_pair(v,temp));vis[v] = true;}else{double temp = (100.0-r)/100.0 * value;q.push(make_pair(v,temp));vis[v] = true;}  }}}long long res = (long long)ans;cout << res << endl;
}
int main(){cin >> N >> Z >> r;for(int i=1;i<=N;i++){int K;cin >> K;if(K==0){int M;cin >> M;hashT[i-1] = M;}else{for(int j=1;j<=K;j++){int v;cin >> v;G[i-1].push_back(v);}}}levelorder(0);return 0;
}

L2-021 点赞狂魔 (25 分)

算法标签: 哈希 + 排序
注意点: 用哈希方法统计不同标签的个数,然后结构体排序输出结果

#include<bits/stdc++.h>
using namespace std;
struct node{string s;int sum = 0;double ave = 0.0;
};
node stu[105];
bool cmp(node stu1,node stu2){if(stu1.sum!=stu2.sum){return stu1.sum > stu2.sum;}else{return stu1.ave < stu2.ave;}
}
int main(){int N;cin >> N;for(int i=1;i<=N;i++){cin >> stu[i].s;int K;cin >> K;set<int> s;for(int j=1;j<=K;j++){int t;cin >> t;s.insert(t);}int cnt =  s.size();stu[i].sum = cnt;stu[i].ave = K*1.0/cnt;}sort(stu+1,stu+1+N,cmp);if(N<3){for(int i=1;i<=N;i++){if(i==1){cout << stu[i].s;}else{cout << " " << stu[i].s;}}for(int i=1;i<=3-N;i++){cout << " " << "-";}}else{for(int i=1;i<=3;i++){if(i==1){cout << stu[i].s; }else{cout << " " << stu[i].s;}}  }return 0;
}

L2-022 重排链表 (25 分)

算法标签: 链表 + 模拟
注意点: 一道关于链表的模拟题,分奇偶交错排列即可,难度不大,注意测试点3,这种情况下给出N个结点,但可连接成链表的结点数少于N个,因此需重新统计真正的结点个数,然后再进行计算!

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int address[maxn];
int nex[maxn];
int value[maxn];
int ans_add[maxn];
int ans_next[maxn];
int ans_value[maxn];
int main(){int S;cin >> S;int N;cin >> N;for(int i=1;i<=N;i++){int add;cin >> add;cin >> value[add] >> nex[add];}int t = S;int NL = 0;while(t!=-1){NL++;t = nex[t];}int N0 = NL/2;int cnt = 1;t = S;while(t!=-1){if(cnt<=N0){ans_value[cnt*2] = value[t];ans_add[cnt*2] = t;}else{int temp = (cnt-N0);temp = temp*2-1;if(NL%2==0){temp = NL-temp;}else{temp = NL-temp+1;}ans_value[temp] = value[t];ans_add[temp] = t;}cnt++;t = nex[t];}for(int i=1;i<=NL-1;i++){ans_next[i] = ans_add[i+1];}ans_next[NL] = -1;for(int i=1;i<=NL-1;i++){printf("%05d %d %05d\n",ans_add[i],ans_value[i],ans_next[i]);}printf("%05d %d %d\n",ans_add[NL],ans_value[NL],-1);return 0;
}

L2-023 图着色问题 (25 分)

算法标签: 图论 + 染色
注意点: 图染色的判断问题,首先是要判断颜色的数目,题目要求用K种颜色进行染色,也就是说,必须使用K种颜色,大于或小于都是不允许的,然后用K种颜色染色,保证无向图中,任意一条边的两个结点都是不同的颜色,最后输出判断的结果

#include<bits/stdc++.h>
using namespace std;vector<int> G[505];
int a[505];
int main(){int V,E,K;cin >> V >> E >> K;for(int i=1;i<=E;i++){int u,v;cin >> u >> v;G[u].push_back(v);G[v].push_back(u); }int N;cin >> N;for(int i=1;i<=N;i++){for(int j=1;j<=V;j++){cin >> a[j];}bool f = false;set<int> s;for(int j=1;j<=V;j++){s.insert(a[j]);}if(s.size()!=K){printf("No\n");}else{for(int u=1;u<=V;u++){for(int j=0;j<G[u].size();j++){int v = G[u][j];if(a[u]!=a[v]){continue;}else{f = true;break;}}if(f){break;}}if(f){printf("No\n");}else{printf("Yes\n");}}}return 0;
}

L2-024 部落 (25 分)

算法标签: 并查集
注意点: 并查集模板题,具体可参考数据结构专题系列-并查集篇

#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005;
int father[maxn];
int a[maxn];
int findfather(int x){if(x==father[x]){return x;}else{int F = findfather(father[x]);father[x] = F;return F; }
}
void Union(int a,int b){int fA = findfather(a);int fB = findfather(b);if(fA!=fB){father[fA] = fB;}
}
set<int> s;
int main(){int N;cin >> N;for(int i=1;i<=10000;i++){father[i] = i;}for(int i=1;i<=N;i++){int K;cin >> K;for(int j=1;j<=K;j++){cin >> a[j];s.insert(a[j]);}for(int j=2;j<=K;j++){Union(a[1],a[j]);}}set<int> s2;for(auto it=s.begin();it!=s.end();it++){int t = *it;s2.insert(findfather(t));}int ans1 = s.size();int ans2 = s2.size();cout << ans1 << " " << ans2 << endl;int Q;cin >> Q;for(int i=1;i<=Q;i++){int u,v;cin >> u >> v;int fx = findfather(u);int fy = findfather(v);if(fx!=fy){cout << "N" << endl;}else{cout << "Y" << endl;}}return 0;
}

L2-025 分而治之 (25 分)

算法标签: 图论 + 枚举
注意点: 枚举每个未被占领的顶点,判断是否连通即可!此处的连通是指不与任何城市有边连通,即孤立的顶点

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
bool hashT[maxn];
vector<int> G[maxn];
int main(){int N,M;cin >> N >> M;for(int i=1;i<=M;i++){int u,v;cin >> u >> v;G[u].push_back(v);G[v].push_back(u);}int K;cin >> K;for(int i=1;i<=K;i++){memset(hashT,0,sizeof(hashT));int NP;cin >> NP;for(int i=1;i<=NP;i++){int t;cin >> t;hashT[t] = true;}bool f = true;for(int i=1;i<=N;i++){if(hashT[i]){continue;}else{for(int j=0;j<G[i].size();j++){int v = G[i][j];if(!hashT[v]){f = false;break;}}if(!f){break;}}}if(f){cout << "YES" << endl;}else{cout << "NO" << endl;}}return 0;
}

L2-026 小字辈 (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 本题考察树的层次遍历,求树中最深结点的深度,并输出最底层叶结点的值

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int layer[maxn];
bool vis[maxn];
vector<int> G[maxn];
void levelorder(int root){queue<int> q;vis[root] = true;q.push(root);while(!q.empty()){int f = q.front(); q.pop();for(int i=0;i<G[f].size();i++){int v = G[f][i];if(!vis[v]){vis[v] = true;layer[v] = layer[f] + 1;q.push(v);}}}
}
int main(){int N;scanf("%d",&N);int root = 0;for(int i=1;i<=N;i++){int t;scanf("%d",&t);if(t==-1){root = i;layer[root] = 1;}else{G[t].push_back(i);}}levelorder(root);int maxm = -1;for(int i=1;i<=N;i++){maxm = max(maxm,layer[i]);}cout << maxm << endl;int cnt = 0;for(int i=1;i<=N;i++){if(layer[i] == maxm){if(!cnt){cout << i;}else{cout << " " << i;}cnt++;}}return 0;
}

L2-027 名人堂与代金券 (25 分)

算法标签: 排序
注意点: 需注意输出排名前K名的成绩单,由于存在并列的可能性,因此输出不一定是K个人

#include<bits/stdc++.h>
using namespace std;
struct node{string s;int score;int rank;
};
const int maxn = 1e4+5;
node stu[maxn];
bool cmp(node stu1,node stu2){if(stu1.score!=stu2.score){return stu1.score>stu2.score;}else{return stu1.s < stu2.s;}
}
int main(){int N,G,K;cin >> N >> G >> K;int ans = 0;for(int i=1;i<=N;i++){cin >> stu[i].s >> stu[i].score;if(stu[i].score>=G){ans += 50;    }else if(stu[i].score>=60){ans += 20;} }cout << ans << endl;sort(stu+1,stu+1+N,cmp);stu[1].rank = 1;for(int i=2;i<=N;i++){if(stu[i].score == stu[i-1].score){stu[i].rank = stu[i-1].rank;}else{stu[i].rank = i;}}for(int i=1;i<=N;i++){if(stu[i].rank<=K){cout << stu[i].rank << " " << stu[i].s << " " << stu[i].score << endl;}else{break;}}return 0;
}

L2-028 秀恩爱分得快 (25 分)

算法标签: 字符串 + 枚举
注意点: 做这道题之前,可以先看这道题:PAT甲级 1139 First Contact (30 分),具体可从[OJ题解系列 目录导航帖]获得
本题难度比那道题略小,坑点数量也少一些,由于可能出现+0与-0元素,-代表女生,+代表男生,因此读入的时候,用字符串读入,再转换成整数,输出时也注意+0与-0的输出
此外,输出A和B的条件为:当且仅当与A最亲密的异性是B,与B最亲密的异性是A,若两者其一不满足,那么就分别输出A最亲密的和B最亲密的

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
int hashT[maxn];
int a[maxn];
double G[maxn][maxn];
int main(){int N,M;scanf("%d%d",&N,&M);for(int i=1;i<=M;i++){int K;scanf("%d",&K);for(int j=1;j<=K;j++){char s[6];scanf("%s",s);int number = 0;if(s[0] == '-'){for(int i=1;i<strlen(s);i++){number = number*10 + s[i]-'0';}hashT[number] = 2;}else{for(int i=0;i<strlen(s);i++){number = number*10 + s[i] -'0';}hashT[number] = 1;}a[j] = number;}double T = 1.0/K;for(int j=1;j<=K-1;j++){for(int k=j+1;k<=K;k++){G[a[j]][a[k]] += T;G[a[k]][a[j]] += T;}}}string sA,sB;cin >> sA >> sB;int f1 = 0,f2 = 0;int A = 0,B = 0;if(sA[0]=='-'){f1 = 2;for(int i=1;i<sA.size();i++){A = A*10 + sA[i]-'0';}}else{f1 = 1;for(int i=0;i<sA.size();i++){A = A*10 + sA[i] - '0';}}if(sB[0]=='-'){f2 = 2;for(int i=1;i<sB.size();i++){B = B*10 + sB[i] - '0';}}else{f2 = 1;for(int i=0;i<sB.size();i++){B = B*10 + sB[i] - '0';}}double maxA = -1.0; double maxB = -1.0;for(int i=0;i<N;i++){if(((f1==2 && hashT[i]==1) || (f1==1 && hashT[i]==2)) && G[A][i]>maxA){maxA = G[A][i];}}for(int i=0;i<N;i++){if(((f2==2 && hashT[i]==1) || (f2==1 && hashT[i]==2)) && G[B][i]>maxB){maxB = G[B][i];}}double ans = G[A][B];if((fabs(ans-maxA)<1e-5 && fabs(ans-maxB)<1e-5)){cout << sA << " " << sB << endl;}else{for(int i=0;i<N;i++){if((f1==2 && hashT[i]==1) && fabs(G[A][i]-maxA)<1e-4){if(A==0){printf("-0 %d\n",i);}else{printf("%d %d\n",-A,i);}}else if((f1==1 && hashT[i]==2) && fabs(G[A][i]-maxA)<1e-4){if(i==0){printf("%d -0\n",A);}else{printf("%d %d\n",A,-i);}  }}for(int i=0;i<N;i++){if((f2==2 && hashT[i]==1) && fabs(G[B][i]-maxB)<1e-4){if(B==0){printf("-0 %d\n",i);}else{printf("%d %d\n",-B,i);}}else if((f2==1 && hashT[i]==2) && fabs(G[B][i]-maxB)<1e-4){if(i==0){printf("%d -0\n",B);}else{printf("%d %d\n",B,-i);}}}}return 0;
}

L2-029 特立独行的幸福 (25 分)

算法标签: 数论 + 模拟
注意点: 按照题目所给的条件模拟即可
(1)注意进入无限循环的判断,当出现了重复元素后,就退出迭代
(2)注意判断数字的“独立性”,将每个数迭代后,到1结束之间的所有数,都用哈希表记录下,未被记录过的数字一定是满足“独立性”的

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e4+5;
int a[maxn];
bool hashT[maxn];
int ans[maxn];
int calcu(int N){int ans = 0;while(N){int u = N%10;ans += u*u;N /=10;}return ans;
}
bool isprime(int N){if(N<2){return 0;}for(int i=2;i<=sqrt(N);i++){if(N%i==0){return 0;}}return 1;
}
int main(){int A,B;cin >> A >> B;for(int i=A;i<=B;i++){int t = i;set<int> s;while(t!=1){t = calcu(t);if(s.find(t) != s.end()){break;}else{s.insert(t);}}if(t == 1){for(auto it=s.begin();it!=s.end();it++){int u = *it;hashT[u] = true;}ans[i] = s.size();}}int cnt = 0;for(int i=A;i<=B;i++){if(!hashT[i] && ans[i]){cnt++;if(isprime(i)){printf("%d %d\n",i,2*ans[i]);}else{printf("%d %d\n",i,ans[i]);}}}if(!cnt){cout << "SAD" << endl;} return 0;
}

L2-030 冰岛人 (25 分)

算法标签: LCA + BFS/DFS
注意点: 一道很坑的题目!
本题存在很多细节以及理解上的误差(题面表述不清晰):
(1)维京人后裔是可以通过姓的后缀判断其性别的,其他人则是在姓的后面加 m 表示男性、f 表示女性。这句话表明带有m/f的后缀既有可能是维京人的祖先,也有可能是不是维京人。
(2)题目保证给出的每个维京家族的起源人都是男性。这句话表明只有m可能是维京人的祖先,f则不是维京人,因此,m/f都没有上一代,在树上无需建立边,而其余情况需建立从child到parent的边(代码中vis数组记录无需建立边的情况,[测试点2]/[测试点4])
(3)题目保证不存在两个人是同名的,这意味着用名做key进行哈希查找
(4)接下来看题面的输出条件:
对每一个查询,根据结果在一行内显示以下信息:
1.若两人为异性,且五代以内无公共祖先,则输出 Yes;
2.若两人为异性,但五代以内(不包括第五代)有公共祖先,则输出 No;
3.若两人为同性,则输出 Whatever;(这里直接判断性别即可,外层if条件判断)
4.若有一人不在名单内,则输出 NA。(任意一个名字哈希查找失败,外层if条件判断)
3、4条件容易判断,1、2条件表述模糊,题目还补充了这么一个条件:
所谓“五代以内无公共祖先”是指两人的公共祖先(如果存在的话)必须比任何一方的曾祖父辈分高。
也就是说,要先找到公共祖先,然后判断该公共祖先不在任一个人的五代以内,比方说,LCA比A高9层,比B高3层,还是在五代以内,应该输出No,此时,我们再回看条件1、2,发现有表述不严谨之处,所谓五代以内,是指层次较高的结点五代以内没有公共祖先,对于层次较低的结点,可以理解为N代内无公共祖先(不限制5层,[测试点3]/[测试点6])

#include<bits/stdc++.h>
using namespace std;
map<string,int> mp1;
map<int,string> mp2;
map<string,int> sex;
const int maxn = 2e5+5;
string C1[maxn];
string C2[maxn];
bool vis[maxn];
vector<int> G[maxn];int cnt = 0;
int check(int u1,int u2){vector<int> v1;v1.push_back(u1);vector<int> v2;v2.push_back(u2); int t1 = G[u1].size();while(t1){v1.push_back(G[u1][0]);u1 = G[u1][0];t1 = G[u1].size();}int t2 = G[u2].size();while(t2){v2.push_back(G[u2][0]);u2 = G[u2][0];t2 = G[u2].size();}if(v1.back() == v2.back()){int size1 = v1.size();int size2 = v2.size();while(size1>0 && size2>0 && v1[size1-1] == v2[size2-1]){size1--;size2--;}size1++;size2++;if(size1>=5 && size2>=5){return 1;}else{return 0;}}else{return 1;}
}int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){string s2,s1;       //s2-name,s1-surnamecin >> s2 >> s1;int len1 = s1.size();string first;if(mp1.find(s2)==mp1.end()){mp1[s2] = ++cnt;mp2[cnt] = s2;}if(s1[len1-1] == 'm'){first = s1.substr(0,len1-1);sex[s2] = 1;vis[mp1[s2]] = true;}else if(s1[len1-1] == 'f'){first = s1.substr(0,len1-1);sex[s2] = 2;vis[mp1[s2]] = true;}else if(s1.substr(len1-4) == "sson"){first = s1.substr(0,len1-4);sex[s2] = 1;}else if(s1.substr(len1-7) == "sdottir"){first = s1.substr(0,len1-7);sex[s2] = 2;}if(mp1.find(first)==mp1.end()){mp1[first] = ++cnt;mp2[cnt] = first;}C1[i] = s2;C2[i] = first;}for(int i=1;i<=N;i++){if(!vis[mp1[C1[i]]]){int u = mp1[C1[i]];int v = mp1[C2[i]];G[u].push_back(v);  }}int M;scanf("%d",&M);for(int i=1;i<=M;i++){string name1,surname1,name2,surname2;cin >> name1 >> surname1 >> name2 >> surname2;if(mp1.find(name1) == mp1.end() || mp1.find(name2) == mp1.end()){printf("NA\n");}else{int t1 = sex[name1];int t2 = sex[name2];if(t1 == t2){printf("Whatever\n");}else{int u1 = mp1[name1];int u2 = mp1[name2];int op = check(u1,u2);if(op){printf("Yes\n");}else{printf("No\n");}}}} return 0;
}

L2-031 深入虎穴 (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 本题考察的算法为求一棵树的最大深度,这里采用DFS方法记录

#include<bits/stdc++.h>
using namespace std;
int N;
const int maxn = 1e5+5;
vector<int> G[maxn];
bool hashT[maxn];
vector<int> temp;
int ans;
int maxm = -1;
void dfs(int root){temp.push_back(root);if(G[root].size()==0){int S = temp.size();if(S>maxm){maxm = S;ans = root;}}else{for(int i=0;i<G[root].size();i++){int v = G[root][i];dfs(v);}}temp.pop_back();
}
int main(){cin >> N;for(int i=1;i<=N;i++){int K;cin >> K;for(int j=0;j<K;j++){int t;cin >> t;G[i].push_back(t);hashT[t] = true;}}int root = -1;for(int i=1;i<=N;i++){if(!hashT[i]){root = i;break;}}dfs(root);cout << ans << endl;return 0;
}

L2-032 彩虹瓶 (25 分)

算法标签: 栈混洗
注意点: 本题考察的是栈结构,给你一个序列,并且限制栈的大小,要求判断该序列是否为栈混洗的序列
当入栈元素超过栈大小时,或者是栈内还存在元素(无法取出)时,都是不合法序列,输出NO,其余情况输出YES

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int main(){int N,M,K;cin >> N >> M >> K;for(int i=1;i<=K;i++){for(int j=1;j<=N;j++){cin >> a[j];}stack<int> s;int cnt = 1;bool f = true;for(int j=1;j<=N;){if(a[j] == cnt){cnt++;j++;}else if(!s.empty() && cnt == s.top()){s.pop();cnt++;}else{s.push(a[j]);j++;if(s.size()>M){f = false;break;}}}while(!s.empty()){if(s.top() == cnt){cnt++;s.pop();}else{break;}}if(!s.empty()){f = false;}if(f){printf("YES\n");}else{printf("NO\n");}} return 0;
}

L2-033 简单计算器 (25 分)

算法标签:
注意点: 栈算法模板题,考察了栈的符号算术功能

#include<bits/stdc++.h>
using namespace std;
int a[1005];
stack<int> s1;
stack<char> s2;
int main(){int N;cin >> N;for(int i=1;i<=N;i++){int t;cin >> t;s1.push(t);}for(int i=1;i<=N-1;i++){char ch;cin >> ch;s2.push(ch);}while(!s2.empty()){int n1 = s1.top();s1.pop();int n2 = s1.top();s1.pop();char ch = s2.top();s2.pop();if(ch == '+'){int ans = n2 + n1;s1.push(ans);}else if(ch == '-'){int ans = n2 - n1;s1.push(ans);}else if(ch == '*'){int ans = n2 * n1;s1.push(ans);}else{if(n1==0){printf("ERROR: %d/0",n2);exit(0);}else{int ans = n2 / n1;s1.push(ans);}}}cout << s1.top() << endl;return 0;
}

L2-034 口罩发放 (25 分)

算法标签: 大模拟 + 排序
注意点: 一道坑题!
由于题意不清,因此理解上可能会有各式各样的问题,首先,梳理一下题目中的各种词汇:
(1)申请信息——每一个数据块给出一天的申请信息、申请信息的每一条记录为申请记录
(2)发放信息——程序输出的发放记录,按照提交时间第一优先级,申请记录顺序第二优先级排序
(3)状况信息——顺序按照申请记录中出现的顺序确定,不重不漏(合法记录指ID号18位,且是数字)
纵观题目的各个条件,我们发现(2)是需要排序的,而(3)是不需要排序的。因此先处理(3),再处理(2)
要确保信息的不重复,则必须采用哈希算法,由于ID号的唯一性,因此用ID作为关键字,建立与name的映射
最后注意一点,ID号必须为18位,且都是数字(不是字符)!

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e4+5;
struct node{string name;string ID;int op;int h;int m;int Day;int number;
};
node stu[1005];int hashT[maxn];
bool vis[maxn];
string ans[maxn];
int res = 0;bool cmp(node stu1,node stu2){if(stu1.h!=stu2.h){return stu1.h < stu2.h;}else if(stu1.m!=stu2.m){return stu1.m < stu2.m;}else{return stu1.number < stu2.number;}
}map<string,int> mp1;
map<int,string> mp2;
map<string,string> mp3;int check(string s){for(int i=0;i<s.size();i++){if(s[i]>='0' && s[i]<='9'){continue;}else{return 0;}} return 1;
}
int main(){int D,P;scanf("%d%d",&D,&P);int cnt = 0;for(int i=0;i<maxn;i++){hashT[i] = -100;}for(int i=1;i<=D;i++){int T,S;scanf("%d%d",&T,&S);for(int j=1;j<=T;j++){cin >> stu[j].name >> stu[j].ID >> stu[j].op;scanf("%d:%d",&stu[j].h,&stu[j].m);stu[j].Day = i;stu[j].number = j;int len = stu[j].ID.size();if(len==18 && check(stu[j].ID)){if(mp1.find(stu[j].ID) == mp1.end()){mp1[stu[j].ID] = ++cnt;mp2[cnt] = stu[j].ID;mp3[stu[j].ID] = stu[j].name;}int id = mp1[stu[j].ID];if(stu[j].op == 1 && !vis[id]){vis[id] = true;ans[res++] = stu[j].ID;}  }}sort(stu+1,stu+1+T,cmp);for(int j=1;j<=T;j++){int len = stu[j].ID.size();if(len==18 && check(stu[j].ID)){if(mp1.find(stu[j].ID) == mp1.end()){mp1[stu[j].ID] = ++cnt;mp2[cnt] = stu[j].ID;mp3[stu[j].ID] = stu[j].name;}int id = mp1[stu[j].ID];int D1 = hashT[id];if(stu[j].Day-D1>P && S>0){S--;hashT[id] = stu[j].Day;cout << stu[j].name << " " << stu[j].ID << endl;}}}}for(int i=0;i<res;i++){cout << mp3[ans[i]] << " " << ans[i] << endl;}return 0;
}

L2-035 完全二叉树的层序遍历 (25 分)

算法标签: 树,二叉树 + 遍历
注意点: 一道好题!这里给出了一种新的建树方式,后序遍历建树(完全二叉树),按序输出即为层次遍历的值

#include<bits/stdc++.h>
using namespace std;
int post[35];
int N;
void postorder(int root){if(root>N){return;} postorder(root * 2);postorder(root * 2 + 1);cin >> post[root];
}
int main(){cin >> N;postorder(1);for(int i=1;i<=N;i++){if(i==1){cout << post[i];}else{cout << " " << post[i];}}return 0;
}

L2-036 网红点打卡攻略 (25 分)

算法标签: 图论 + 哈密尔顿环路
注意点: 本题考察哈密尔顿环路问题,首先需要判断哈密尔顿环路是否满足(路径连通,且访问每个顶点仅一次),满足条件则统计,并记录最短路径和当前的方案编号

#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
int G[205][205];
int a[205];
bool hashT[205];
int main(){memset(G,0x3f,sizeof(G));int N,M;cin >> N >> M;for(int i=1;i<=M;i++){int u,v,w;cin >> u >> v >> w;G[u][v] = G[v][u] = w;} int K;cin >> K;int cnt = 0;int maxm = 0x3f3f3f3f;int site = -1;for(int i=1;i<=K;i++){memset(hashT,0,sizeof(hashT));memset(a,0,sizeof(a));int n;cin >> n;for(int j=1;j<=n;j++){cin >> a[j];hashT[a[j]] = 1;}if(n!=N){continue;}else{bool f = true;for(int i=1;i<=N;i++){if(hashT[i]){continue;}else{f = false;break;}}if(f){int ans = 0;bool f2 = true;for(int i=1;i<=N+1;i++){if(G[a[i-1]][a[i]]!=0x3f3f3f3f){ans += G[a[i-1]][a[i]];}else{f2 = false;break;}}if(f2){cnt++;if(ans<maxm){maxm = ans;site = i;}}}}}cout << cnt << endl;cout << site << " " << maxm << endl;return 0;
}

L2-037 包装机 (25 分)

算法标签: 模拟
注意点: 按照题目操作要求模拟包装机的过程,注意栈和队列的判空!

#include<bits/stdc++.h>
using namespace std;
queue<char> q[105];
stack<int> s;
string out = "";
int main(){int N,M,Smax;scanf("%d%d%d",&N,&M,&Smax);for(int i=1;i<=N;i++){for(int j=1;j<=M;j++){char t;cin >> t;q[i].push(t);}}int op;int cnt = 0;while(scanf("%d",&op) && op!=-1){if(op == 0){if(!s.empty()){char t = s.top();s.pop();out += string(1,t);cnt--;}}else{if(!q[op].empty()){char f = q[op].front();q[op].pop();if(cnt == Smax){char t = s.top();s.pop();out += string(1,t);s.push(f);}else{s.push(f);cnt++;}}}}cout << out << endl;return 0;
}

L2-038 病毒溯源 (25 分

算法标签: 树,二叉树 + DFS遍历
注意点: 首先找到根结点root(不是任何子结点的结点一定是根结点),然后从根结点开始执行DFS遍历,即可求出最大深度,输出字典序较小的结果即可

#include<bits/stdc++.h>
using namespace std;
int N;
const int maxn = 1e4+5;
vector<int> G[maxn];
bool hashT[maxn];
vector<int> temp;
vector<int> ans;
int maxm = -1;
void dfs(int root){temp.push_back(root);if(G[root].size()==0){int S = temp.size();if(S>maxm){maxm = S;ans = temp;}else if(S == maxm){if(temp<ans){ans = temp;}}}else{for(int i=0;i<G[root].size();i++){int v = G[root][i];dfs(v);}}temp.pop_back();
}
int main(){cin >> N;for(int i=0;i<N;i++){int K;cin >> K;for(int j=0;j<K;j++){int t;cin >> t;G[i].push_back(t);hashT[t] = true;}}int root = -1;for(int i=0;i<N;i++){if(!hashT[i]){root = i;break;}}dfs(root);cout << ans.size() << endl;for(int i=0;i<ans.size();i++){if(i==0){cout << ans[i];}else{cout << " " << ans[i];}}return 0;
}

L2-039 清点代码库 (25 分)

算法标签: 哈希 + 排序
注意点: 这道题考察哈希算法,我们需要将一串“输出值”,通过哈希函数映射成一个数,从而满足题目中的查询要求,这里采用STL的map容器实现
首先读入不同模块的输入,若该组输入在哈希表中出现过,那么我们只需要将该模块的计数器+1,若没有出现过,那么我们需要在哈希表中建立一个映射,并将模块计数器初始化为1,输入结束后,我们对结构体进行排序,得到最终的答案!

#include<bits/stdc++.h>
using namespace std;
vector<int> V[10005];
struct node{int number;int ans = 0;
};
node r[10005];map<vector<int>,int> mp;
map<int,vector<int> > mp2;
bool cmp(node r1,node r2){if(r1.ans!=r2.ans){return r1.ans > r2.ans;}else{vector<int> v1;vector<int> v2;v1 = mp2[r1.number];v2 = mp2[r2.number];return v1 < v2;}
}
int main(){int N,M;scanf("%d%d",&N,&M);for(int i=1;i<=N;i++){for(int j=1;j<=M;j++){int t;scanf("%d",&t);V[i].push_back(t);}}int cnt = 0;for(int i=1;i<=N;i++){if(mp.find(V[i])==mp.end()){mp[V[i]] = ++cnt;mp2[cnt] = V[i];r[cnt].ans = 1;r[cnt].number = cnt;}else{r[mp[V[i]]].ans++;}}sort(r+1,r+1+cnt,cmp);printf("%d\n",cnt);for(int i=1;i<=cnt;i++){printf("%d",r[i].ans);vector<int> v = mp2[r[i].number];for(int j=0;j<v.size();j++){printf(" %d",v[j]);}printf("\n");}return 0;
}

L2-040 哲哲打游戏 (25 分)

算法标签: 大模拟
注意点: 本题考察的算法是大模拟,按照题目的要求,模拟游戏的读档、存档操作,哈希数组用来存档,读取也从该数组中取出,注意本题的剧本从1开始

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
int hashT[105];
vector<int> G[maxn];
int main(){int N,M;scanf("%d%d",&N,&M);for(int i=1;i<=N;i++){int K;scanf("%d",&K);for(int j=1;j<=K;j++){int t;scanf("%d",&t);G[i].push_back(t);} }int start = 1;for(int i=1;i<=M;i++){int op,x;scanf("%d%d",&op,&x);if(op == 0){start = G[start][x-1];}else if(op == 1){hashT[x] = start;printf("%d\n",start);}else{start = hashT[x];}}printf("%d\n",start);return 0;
}

L2-041 插松枝(25分)

算法标签: 模拟 + 队列/栈
注意点: 易知本题考察的是队列/栈,小盒子是栈,推送器是队列
根据题目的要求,我们可以将其分成2个环节处理:推送器上还有小松针/推送器上没有小松针:
(1)推送器上还有小松针:此时先检查盒子内是否有松针,若有,则按要求不超过K个且满足松针大小单调不递增性质依次pop,直至不能pop时,若记录的小松针个数为K个,那么直接输出,否则,依次检查推送器上的小松针,满足要求的加入,直至K个输出;不满足要求的加入小盒子,此时若小盒子已满,也直接输出,这里的检查是序号单调递增的,N个检查完之后进入(2)环节,即没有小松针在推送器上了
(2)推送器上没有小松针:此时检查小盒子内是否有小松针,若有,则按要求不超过K个且满足松针大小单调非递增性质依次pop,直至empty

#include<bits/stdc++.h>
using namespace std;
int a[1005];
int b[1005];
int cnt = 1;
stack<int> s;
int main(){int N,M,K;scanf("%d%d%d",&N,&M,&K);for(int i=1;i<=N;i++){scanf("%d",&a[i]);}while(cnt<=N){int count = 0;int Height = 999;while(!s.empty() && count < K){if(s.top()<=Height){Height = s.top();b[++count] = s.top();s.pop();}else{break;}}if(count == K){for(int i=1;i<=count;i++){if(i == 1){printf("%d",b[i]);}else{printf(" %d",b[i]);}}printf("\n");}else{while(cnt<=N && count<K){if(a[cnt]<=Height){b[++count] = a[cnt];Height = a[cnt];cnt++;}else{int size = s.size();if(size<M){s.push(a[cnt]);cnt++;}else{break;}}}for(int i=1;i<=count;i++){if(i == 1){printf("%d",b[i]);}else{printf(" %d",b[i]);}}printf("\n");}}while(!s.empty()){int count = 0;int Height = 999; while(!s.empty() && count<K && s.top()<=Height){b[++count] = s.top();Height = s.top();s.pop();}for(int i=1;i<=count;i++){if(i == 1){printf("%d",b[i]);}else{printf(" %d",b[i]);}}printf("\n");      }return 0;
}

L2-042 老板的作息表(25分)

算法标签: 排序

#include<bits/stdc++.h>
using namespace std;
struct node{int start;int end;
};
const int maxn = 1e5+5;
node t[maxn];
bool cmp(node t1,node t2){if(t1.start!=t2.start){return t1.start < t2.start;}else{return t1.end < t2.end;}
}
int time_to_int(int h,int m,int s){return 3600*h + 60*m + s;
}
void int_to_time(int t1,int t2){int h1 = t1/3600;int m1 = t1%3600/60;int s1 = t1%60;int h2 = t2/3600;int m2 = t2%3600/60;int s2 = t2%60;printf("%02d:%02d:%02d - %02d:%02d:%02d\n",h1,m1,s1,h2,m2,s2);
}
int main(){int N;scanf("%d",&N);for(int i=1;i<=N;i++){int h1,h2,m1,m2,s1,s2;scanf("%d:%d:%d - %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);t[i].start = time_to_int(h1,m1,s1);t[i].end = time_to_int(h2,m2,s2);}sort(t+1,t+1+N,cmp);int begin = 0;for(int i=1;i<=N;i++){if(t[i].start>begin){int_to_time(begin,t[i].start);begin = t[i].end;}else{begin = t[i].end;}}if(begin!=86399){int_to_time(begin,86399);}return 0;
}

L2-043 龙龙送外卖(25分)

L2-044 大众情人(25分)

算法标签: 图论 + Floyd
注意点: Floyd模板题,算法细节具体可详见数据结构专题系列——最短路
本题需仔细理解这句话:我们记一个人iii在一个异性jjj眼中的距离感为Dij;D_{ ij};Dij​;将iii的“异性缘”定义为 1maxj∈S(i)(Dij​)\frac{1}{max_{j∈S(i)}{(D_{ij}​ )}}maxj∈S(i)​(Dij​​)1​,其中S(i)S(i)S(i)是相对于iii的所有异性的集合。那么“大众情人”就是异性缘最好(值最大)的那个人。
要使得值最大,那么就是求max(Dij)max(D_{ij})max(Dij​)最小的那组结果;
相对于iii的所有异性的集合,这意味着我们比较的是j眼中的i尽可能小,用数据结构语言描述为dp[j][i]最小(注意不是dp[i][j])

#include<bits/stdc++.h>
using namespace std;
int hashT[505];
int dp[505][505];
int res[505];int main(){int N,M;scanf("%d%d",&N,&M);memset(dp,0x3f,sizeof(dp));for(int i=1;i<=N;i++){dp[i][i] = 0;}for(int i=1;i<=N;i++){char sex;cin >> sex;if(sex == 'F'){hashT[i] = 2;}else{hashT[i] = 1;}int K;scanf("%d",&K);for(int j=1;j<=K;j++){int num,dis;scanf("%d:%d",&num,&dis);dp[i][num] = min(dp[i][num],dis);}}for(int k=1;k<=N;k++){for(int i=1;i<=N;i++){for(int j=1;j<=N;j++){dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]);   }}  }int maxm = INT_MAX;for(int i=1;i<=N;i++){if(hashT[i] == 2){int maxt = -1;for(int j=1;j<=N;j++){if(hashT[j] == 1){maxt = max(maxt,dp[j][i]);}}maxm = min(maxm,maxt);}}int cnt = 0;for(int i=1;i<=N;i++){if(hashT[i] == 2){int maxt = -1;for(int j=1;j<=N;j++){if(hashT[j] == 1){maxt = max(maxt,dp[j][i]); }}if(maxt == maxm){if(!cnt){printf("%d",i);}else{printf(" %d",i);}cnt++;}} }printf("\n");maxm = INT_MAX;cnt = 0;for(int i=1;i<=N;i++){if(hashT[i] == 1){int maxt = -1;for(int j=1;j<=N;j++){if(hashT[j] == 2){maxt = max(maxt,dp[j][i]);}}maxm = min(maxm,maxt);}}for(int i=1;i<=N;i++){if(hashT[i] == 1){int maxt = -1;for(int j=1;j<=N;j++){if(hashT[j] == 2){maxt = max(maxt,dp[j][i]); }}if(maxt == maxm){if(!cnt){printf("%d",i);}else{printf(" %d",i);}cnt++;}} }printf("\n");return 0;
}

团体程序设计天梯赛-L2组相关推荐

  1. 团体程序设计天梯赛 L2 题目合集

    前言 发现自己还能再参加一次天梯赛,在高兴之余,决定把在赛前将所有的天梯赛真题过一遍,希望自己可以取得理想的成绩.目前 L1 的题目已经刷完,打算在赛前刷完 L2 的题目. 本来想 L2 的题目都写个 ...

  2. 第八届cccc团体程序设计天梯赛——个人参赛总结——无代码纯粹的参赛总结

    第八届cccc团体程序设计天梯赛--个人参赛总结--无代码纯粹的参赛总结 目录 第八届cccc团体程序设计天梯赛--个人参赛总结--无代码纯粹的参赛总结 引言~介绍一下cccc天梯赛(==选读==) ...

  3. 【CCCC】PAT : 团体程序设计天梯赛-练习集 L2 答案,题解,附代码

    [CCCC]PAT : 团体程序设计天梯赛-练习集 L2 答案 鉴定完毕,全部水题 ヾ(•ω•`)o 知识点分类(32): 1.树锯结构(9):二叉树的存储,编号,遍历顺序转换,求深度,底层节点,从底 ...

  4. 2021年团体程序设计天梯赛-总决赛L2题解

    2021年团体程序设计天梯赛-总决赛! L2-1 包装机 思路:模拟 代码: #include<bits/stdc++.h> using namespace std; int main() ...

  5. PTA|团体程序设计天梯赛-练习题库集

    文章目录 关于爬取脚本的编写 L1-001 Hello World! (5 分) L1-002 打印沙漏 (15 分) L1-003 个位数统计 (15 分) L1-004 计算摄氏温度 (5 分) ...

  6. 2018团体程序设计天梯赛 软件学院选拔赛

    2018团体程序设计天梯赛 软件学院选拔赛 被你们虐了一下午的OJ是很辛苦的,让我们来看看题解吧. L1-01 微妙的平衡 题目描述: 平衡是一种很微妙的状态.施加在一个物体上各种力,在什么情况下会使 ...

  7. 计算机能力挑战赛_蓝桥杯、PAT、CCF CSP、团体程序设计天梯赛、传智杯、计算机能力挑战赛、软考等大学生编程比赛/考试介绍...

    介绍7个适合普通大学生参加的编程比赛/考试(注:有的比赛如蓝桥杯有多种赛别,本文仅介绍其中的程序设计/编程比赛). 编程入门书籍推荐<算法笔记>,内容详细易懂,对新手非常友好,描述语言为C ...

  8. ptaa乘以b_PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中……)...

    C++ CPP C++语言开发 PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中--) PTA|团体程序设计天梯赛-练习题目题解锦集(持续更新中) 实现语言:C/C++:     ...

  9. PTA|团体程序设计天梯赛-练习题目题解锦集(C/C++)(持续更新中……)

    PTA|团体程序设计天梯赛-练习题目题解锦集(持续更新中) 实现语言:C/C++:      欢迎各位看官交流讨论.指导题解错误:或者分享更快的方法!! 题目链接:https://pintia.cn/ ...

最新文章

  1. numpy 筛选面积最大
  2. 为ios 应用程序添加图标和添加名字
  3. 微服务实践分享(8) 控制调用中心
  4. 实现延时任务的 4 种实现方案!
  5. 利用最小二乘法,用直线拟合点时,为什么计算竖直距离而非垂直距离?为什么在线性回归分析中,求的是距离平方和最小,而不是距离之和最小?
  6. 如何理解拓扑排序算法(转)
  7. 【C++面向对象】类的数据成员:绑定、布局和存取
  8. html toggle自动隐藏,Javascript / HTML – 切换可见性(当另一个div元素呈现可见时自动导致一个div元素隐藏)...
  9. 如何将一个String和多个String值进行比较
  10. 使用uddi sdk发布服务到UDDI时的安全配置
  11. JavaScript高级程序设计(第2版)pdf
  12. 关于路由器,摄像头,防火墙的搜索方法(IOT设备)
  13. 【随文杂想】超长图PS 切片为打印机 A4纸大小打印
  14. 是指因计算机网络不安全导致的风险,网络安全知识竞赛题库
  15. EXCEL表格-输入身份证号无法正常展示问题详解
  16. EasyWeChat实现微信真实支付操作
  17. 通过故障恢复控制台修复xp系统引导文件丢失的方法
  18. “思特奇杯”编程之星初赛
  19. 2022-2027年中国金融服务业RFID行业发展前景及投资战略咨询报告
  20. visual code rg.exe或者git for window占用内存越来越大

热门文章

  1. DLP投影机投影技术之成像原理与工作流程
  2. BPA文件解析及保存
  3. 离线文档编辑、知识管理神器:MyBase
  4. post方式返回文件流实现前端blob下载,responseType: ‘blob‘无效
  5. c语言 bnf,BNF
  6. 戴尔g3最新版的声卡,有可能导致插上耳机没有声音
  7. 解决耳机插入电脑声音仍然外放的问题方法
  8. 《中华人民共和国个人信息保护法》
  9. gcc升级到 6.3.0版本
  10. apk、dex、odex梳理