PAT(甲级)2020年秋季考试
7-1 Panda and PP Milk (20分)
题意: n 只熊猫排成一排喝奶。每只熊猫至少分配 200ml 的牛奶,如果一个熊猫比它旁边的熊猫重,那么就需要比旁边的熊猫至少多喝 100ml 的牛奶。如果体重相同,分配的牛奶要相同。问最少需要分配多少的牛奶,才能满足要求
思路:从左往右扫一遍,每只熊猫都和左边的比。然后从右往左扫一遍,每只熊猫都和右边的比。这样就可以满足条件了。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n;
int a[maxn],val[maxn];
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
int cur=10000;
for(int i=1; i<=n; ++i)
{
if(a[i]>cur) val[i]=val[i-1]+100;
else if(a[i]==cur) val[i]=val[i-1];
else val[i]=200;
cur=a[i];
}
cur=10000;
for(int i=n; i>=1; --i)
{
if(a[i]>cur)
{
val[i]=max(val[i+1]+100,val[i]);
}
else if(a[i]==cur)
{
val[i]=max(val[i],val[i+1]);
}
else val[i]=max(val[i],200);
cur=a[i];
}
int ans=0;
for(int i=1; i<=n; ++i) ans+=val[i];
printf("%d\n",ans);
return 0;
}
7-2 How Many Ways to Buy a Piece of Land (25分)
题意:给定 n 块地,m 块钱,每块地的价格为 a i a_i ai 。你可以选择一个区间 [ l , r ] [l,r] [l,r] 买地,问有几种不同的买法?
思路:二分。枚举起点 i,对每一个 i 找到最右边可以买的地方。中间的都是可以选择的。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n,m;
int a[maxn],pref[maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]),pref[i]=pref[i-1]+a[i];
int ans=0;
for(int i=1; i<=n; ++i)
{
int L=i,R=n;
while(L<R)
{
int mid=(L+R+1)>>1;
if(pref[mid]-pref[i-1]<=m) L=mid;
else R=mid-1;
}
if(pref[L]-pref[i-1]<=m) ans+=L-i+1;
}
printf("%d\n",ans);
return 0;
}
7-3 Left-View of Binary Tree (25分)
题意:给定中序和前序遍历的结果,求一颗二叉树的左视图
思路:常规建树操作。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
int n;
int a[maxn],b[maxn];
struct Node
{
int val,depth;
Node* ls,* rs;
};
Node* build(int l1,int r1,int l2,int r2,int depth)
{
if(l1>r1) return NULL;
int pos;
for(pos=l1; pos<=r1; ++pos)
if(a[pos]==b[l2]) break;
int len1=pos-l1;
int len2=r1-pos;
Node* node=new Node;
node->val=b[l2];
node->depth=depth;
node->ls=build(l1,pos-1,l2+1,l2+len1,depth+1);
node->rs=build(pos+1,r1,l2+len1+1,r2,depth+1);
return node;
}
int visit[maxn];
vector<int> ans;
void bfs(Node* root)
{
queue<Node*> q;
q.push(root);
while(!q.empty())
{
Node* t=q.front();
q.pop();
if(!visit[t->depth])
{
visit[t->depth]=1;
ans.push_back(t->val);
}
if(t->ls!=NULL) q.push(t->ls);
if(t->rs!=NULL) q.push(t->rs);
}
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; ++i) scanf("%d",&a[i]);
for(int i=1; i<=n; ++i) scanf("%d",&b[i]);
Node* root=build(1,n,1,n,1);
bfs(root);
int m=ans.size();
for(int i=1; i<=m; ++i) printf("%d%c",ans[i-1],i==m?'\n':' ');
return 0;
}
7-4 Professional Ability Test (30分)
题意:有 n 个等级,等级之间存在前置关系。假设 A 等级是 B 等级的前置,A 需要达到 S 分,才能达到 B 等级,并且会获得 D 元的代金券。现有 m 个关系,k 个询问,问 T 点能否直接到达,或者求最短(分数最少)的达到 T 的路径。如果最短路相同,则输出获得代金券最多的路径。
思路:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1010,inf=1e9;
int n,m;
struct Egde
{
int v,w,val;
};
vector<Egde> e[maxn];
int in[maxn],dis[maxn],val[maxn],pre[maxn];
int op[maxn],out[maxn];
void topo()
{
for(int i=0; i<=n-1; ++i)
{
dis[i]=inf;
val[i]=0;
pre[i]=-1;
}
queue<int> q;
for(int i=0; i<=n-1; ++i)
{
if(in[i]==0)
{
q.push(i);
dis[i]=0;
val[i]=0;
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(auto x: e[u])
{
int v=x.v,w=x.w;
in[v]--;
if(in[v]==0) q.push(v);
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
val[v]=val[u]+x.val;
pre[v]=u;
}
else if(dis[v]==dis[u]+w)
{
if(val[v]<val[u]+x.val)
{
val[v]=val[u]+x.val;
pre[v]=u;
}
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1; i<=m; ++i)
{
int u,v,s,d;
cin>>u>>v>>s>>d;
e[u].push_back({v,s,d});
in[v]++;
out[v]++;
}
topo();
int k;
scanf("%d",&k);
for(int i=1; i<=k; ++i) scanf("%d",&op[i]);
bool ok=1;
for(int i=1; i<=k; ++i)
if(dis[op[i]]==inf) ok=0;
if(ok)
{
puts("Okay.");
for(int i=1; i<=k; ++i)
{
vector<int> ans;
for(int p=op[i]; p!=-1; p=pre[p]) ans.push_back(p);
reverse(ans.begin(),ans.end());
int m=ans.size();
if(m==1) printf("You may take test %d directly.\n",op[i]);
else for(int i=1; i<=m; ++i) printf("%d%s",ans[i-1],i==m?"\n":"->");
}
}
else
{
puts("Impossible.");
for(int i=1; i<=k; ++i)
{
if(out[op[i]]!=0) puts("Error.");
else printf("You may take test %d directly.\n",op[i]);
}
}
return 0;
}
总结
7-1:左右扫一遍即可。一开始想的是以大小来贪心,会有点错误。。
7-2:二分结束之后,需要check一下,这个二分的结果 L 是否符合要求。
7-3:无
7-4:无