1. 知识点总结
耗时:2h
得分:100/100
知识点:树的层次遍历、字符串处理和哈希表(二次探查解决冲突)
题目 | 难度 | 知识点 |
---|---|---|
1076 Forwards on Weibo | 🎯🎯 | 层次遍历树 |
1077 Kuchiguse | 🎯 | 字符串处理 |
1078 Hashing | 🎯 | 哈希表解决冲突 |
1079 Total Sales of Supply Chain | 🎯 | 层次遍历树 |
2. 分题题解
2.1 1076 Forwards on Weibo
这题的主要难点在于计算forwards
的英文理解,也就是先根据题干构建好图的结构之后,层次遍历求解每一层forwrd的总人数,一共需要计算[1,L]层的总人数,默认当前被询问的节点是第0层.
卡了半小时,原因是我理解的indirect是和当前节点没有直接边的,但是最后AC的版本中可以看到,题目的indirect指的是非当前节点本身.
#include<bits/stdc++.h>
using namespace std;
int N,L,K,num,id,fid;
struct Node{
int level;
vector<int>followers;
};
vector<Node>nodes;
vector<bool>vis;
void levelCount(int root){
int cnt=0;
fill(vis.begin(),vis.end(),false);
queue<int>q;
q.push(root);
vis[root]=true;
nodes[root].level=0;
while(!q.empty()){
int top=q.front();
q.pop();
//bprintf("level:%d val:%d\n",nodes[top].level,top);
if(nodes[top].level<=L){
cnt++;
}else{
break;
}
for(int i=0;i<nodes[top].followers.size();i++){
int cid=nodes[top].followers[i];
if(!vis[cid]){
vis[cid]=true;
nodes[cid].level=nodes[top].level+1;
q.push(cid);
}
}
}
printf("%d",cnt-1);
}
int main(){
scanf("%d%d",&N,&L);
nodes.resize(N+1);
vis.resize(N+1,false);
for(int i=1;i<=N;i++){
scanf("%d",&num);
for(int j=0;j<num;j++){
scanf("%d",&fid);
//构建图结构
nodes[fid].followers.push_back(i);
}
}
scanf("%d",&K);
while(K--){
//处理
scanf("%d",&id);
levelCount(id);
if(K){
printf("\n");
}
}
return 0;
}
2.2 1077 Kuchiguse
找出给定字符串的最长公共后缀,属于基础题~
#include<bits/stdc++.h>
using namespace std;
int N;
//输出最长的公共子串
vector<string>strs;
string ans;
void getSuffix(string a,string& b){
int lena=a.length();
int lenb=b.length();
int i;
string c="";
for(i=0;i<min(lena,lenb);i++){
if(a[lena-i-1]!=b[lenb-i-1]){
break;
}else{
c+=a[lena-i-1];
}
}
reverse(c.begin(),c.end());
b=c;
}
int main(){
scanf("%d",&N);
strs.resize(N);
getchar();
for(int i=0;i<N;i++){
getline(cin,strs[i]);
}
ans=strs[0];
for(int i=1;i<N;i++){
getSuffix(strs[i],ans);
if(ans==""){
break;
}
}
//输出答案
if(ans==""){
printf("nai");
}else{
printf("%s",ans.c_str());
}
return 0;
}
2.3 1078 Hashing
哈希表二次探查解决冲突,主要难点在于英文Quadratic probing (with positive increments only) is used to solve the collisions.
的理解:二次探测(仅具有正增量)用于解决冲突。(来自百度翻译)
#include<bits/stdc++.h>
using namespace std;
int MSize,N,temp;
bool isPrime(int x){
if(x<=1)return false;
if(x==2||x==3||x==5||x==7){
return true;
}
for(int i=2;i*i<=x;i++){
if(x%i==0){
return false;
}
}
return true;
}
vector<int>table;
int Hash(int x){
int pos=-1;
for(int i=0;i<MSize;i++){
int tpos=(i*i+x)%MSize;
if(table[tpos]==-1){
pos=tpos;
break;
}
}
return pos;
}
int main(){
scanf("%d%d",&MSize,&N);
while(!isPrime(MSize)){
MSize++;
}
table.resize(MSize,-1);
for(int i=0;i<N;i++){
scanf("%d",&temp);
//hash查找位置
int pos=Hash(temp);
if(i){
printf(" ");
}
if(pos==-1){
printf("-");
}else{
table[pos]=temp;
printf("%d",pos);
}
}
return 0;
}
2.4 1079 Total Sales of Supply Chain
这个背景的题干遇到很多次了,都是层次遍历树的变式,主要是构建好树之后输出叶子节点价格x货量
的总和
#include<bits/stdc++.h>
using namespace std;
int N,root=0;
double P,r,total_price=0;
struct Node{
int K;
double price;
int sum;
vector<int>childs;
};
vector<Node>nodes;
void levelTravel(int root){
queue<int>q;
nodes[root].price=P;
q.push(root);
while(!q.empty()){
int top=q.front();
q.pop();
for(int i=0;i<nodes[top].K;i++){
int cid=nodes[top].childs[i];
nodes[cid].price=nodes[top].price*(1+r/100);
q.push(cid);
}
if(nodes[top].K==0){
total_price+=nodes[top].price*nodes[top].sum;
}
}
}
int main(){
scanf("%d%lf%lf",&N,&P,&r);
nodes.resize(N);
for(int i=0;i<N;i++){
scanf("%d",&nodes[i].K);
if(nodes[i].K==0){
scanf("%d",&nodes[i].sum);
continue;
}
nodes[i].childs.resize(nodes[i].K);
for(int j=0;j<nodes[i].K;j++){
scanf("%d",&nodes[i].childs[j]);
}
}
levelTravel(root);
printf("%.1f",total_price);
return 0;
}