2025 USACO Feb 银组题解合集
A
考虑从大到小考虑每一个取值的数,如果能换就换,如果换了没用就不换。
实现上使用 vector 存下标,复杂度 \(O(n)\)。
#include<bits/stdc++.h>
using namespace std;
int t,n,m,a[1000005],flag,tim;
vector<int> v[1000005],ans,out;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
v[a[i]].push_back(i);
}
ans.push_back(0);
ans.push_back(0);
m=ans.size();
for(int i=n;i>=1;i--){
if(!v[i].size()) continue;
flag=false;
for(int j=0;j<v[i].size();j++){
if(v[i][j]<ans[m-1] && v[i][j]>ans[m-2]) flag=true;
}
if(flag && !tim){
tim=1;
ans[m-1]=ans[m-2];
}
for(int j=0;j<v[i].size();j++){
if(v[i][j]>ans[m-1]) ans.push_back(v[i][j]),out.push_back(i);
}
m=ans.size();
}
cout<<out[0];
for(int i=1;i<out.size();i++){
cout<<' '<<out[i];
}
tim=m=0;
out.clear();
ans.clear();
for(int i=1;i<=n;i++){
v[i].clear();
}
if(t) cout<<'\n';
}
return 0;
}
B
考虑建出树,然后倒序考虑每一个叶子。每次询问时,暴力跳父亲并标记节点,这个叶子的答案就是最后一个没有被标记的祖先的深度。
实现上 dfs 即可,复杂度 \(O(n)\)。
#include<bits/stdc++.h>
using namespace std;
int n,m,x,cnt[1000005],w[1000005],ans[1000005];
int head[1000005],nxt[2000005],target[2000005],tot;
void add(int x,int y){
tot++;
nxt[tot]=head[x];
head[x]=tot;
target[tot]=y;
}
int dep[1000005],vis[1000005],f[1000005];
void dfs(int x,int fa){
for(int i=head[x];i;i=nxt[i]){
int y=target[i];
if(y==fa) continue;
f[y]=x;
dep[y]=dep[x]+1;
dfs(y,x);
}
}
int find(int x){
while(!vis[f[x]] && x){
vis[x]=1;
x=f[x];
}
vis[x]=1;
return dep[x];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>x;
add(x,i);
cnt[x]++;
cnt[i]++;
}
for(int i=1;i<=n;i++){
if(cnt[i]==1) m++;
}
for(int i=1;i<=m;i++){
cin>>w[i];
}
dfs(0,0);
for(int i=m;i>=1;i--){
ans[i]=find(w[i]);
}
for(int i=1;i<=m;i++){
cout<<ans[i]<<'\n';
}
return 0;
}
C
注意到如果从最终状态往前推,每次能够进行的操作是唯一的。
然后瓶颈在于加快这个模拟过程。
不难发现,在大部分情况下,\((a,b) \to (a\bmod b,b)\)。
然后就可以每次判断能否这么做,直接搜索即可。
复杂度 \(O(log v)\)。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,a,b,c,d;
int solve(int a,int b,int c,int d,int val){
if(!a || !b || a<c || b<d) return -1;
if(a<b) swap(a,b),swap(c,d);
if(b==d && a%b==c%b) return val+(a-c)/b;
else return solve(a%b,b,c,d,val+a/b);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--){
cin>>c>>d>>a>>b;
cout<<solve(a,b,c,d,0)<<'\n';
}
return 0;
}