window.cnblogsConfig = { homeTopImg: [ "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png", "https://cdn.luogu.com.cn/upload/image_hosting/clcd8ydf.png" ], }

USACO 2023-2024 赛季复盘

【USACO23DEC】Cu 复盘

我先用了一个号打,然后是 T1 TLE * 4,T2 AC,T3 WA * 2。然后后面开了一个号调了一些,喜提阿克。

T1:

首先我们知道,对于 a1 每一次是最先吃糖果的。
所以必然有两个情况:

  • 全部给他吃了
  • 吃了一些

首先情况一,我们可以直接特判掉。
剩下情况二,吃了一些没吃完代表:吃了自己的高度,相当于身高乘2。于是我们只需要进行 log109 次。然后后面直接 O(n) 暴力。时间复杂度 O(nlog109)

#include <bits/stdc++.h> using namespace std; const int N = 2e5+5; #define int long long int n,m; int a[N],b[N]; void solve(){ cin >> n >> m; for(int i = 1;i <= n;i++) cin >> a[i]; for(int i = 1;i <= m;i++) cin >> b[i]; for(int i = 1;i <= m;i++){ if(b[i] <= a[1]){ a[1]+=b[i]; continue; } int tmp = 1; for(int j = 1;j <= n;j++) if(a[j] >= tmp && tmp <= b[i]){ int t=a[j]+1; a[j] += min(a[j]-tmp+1,b[i]-tmp+1); tmp = t; } } for(int i = 1;i <= n;i++) cout<<a[i]<<endl; } signed main(){ ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); solve(); return 0; }

T2

这是我第一次唯一场切的一道题:

首先我在这题上写了三份代码。原因是我一开始想到分讨,写复杂了。

根据贪心策略,很容易知道:天数越大,奶牛数少,所以我们让天数最多。
然后我们会发现头尾的那个区间如果是 x,那么相当于一个 2×x1 的一个普通区间(就是在中间的那种区间)。

所以我们根据处理后的每一个区间的长度进行计算,然后得到了每一个区间最小的天数,也就是我们能够放最多的天数。

所以按照这个去模拟即可。

#include <bits/stdc++.h> using namespace std; #define int long long int n; int xx=-1,yy=-1; string s; vector<pair<int,bool> > v; int res,ok=1,cnt=0; int minn = 1e9; void solve(){ cin >> n >> s; s = ' '+s; for(int i = 1;i <= n;i++){ if(s[i]=='0'){ if(res)v.push_back({res,ok}); ok=0; res=0; }else if(s[i]=='1'){ res++;cnt++; } } if(res) v.push_back({res,1}); int min2=1e9; for(auto it:v){ if(it.second == 0)min2 = min(min2,it.first); else{ min2 = min(min2,it.first * 2-1); if(xx == -1) xx = it.first; else yy = it.first; } } minn=(min2+1)/2; int res=0; for(auto it:v){ if(it.first % (minn * 2 - 1) == 0) res+=it.first / (minn * 2 - 1); else res+=it.first / (minn * 2 - 1) + 1; } cout<<res; } signed main(){ ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); solve(); return 0; }

T3

高级的说:解个不等式,低级的说:前缀和。

首先,我们先将所有 a 变换位置到最终应该在的位置。

然后,我们可以通过 aiai1 的高度差和速度差,算出来他们之间还需要多久可以符合要求,或者是多久就不符合要求了。拿出草稿纸,自己列举四种情况分别讨论。

如果这个点开始合法,那么在这里进行标记,如果这里开始不合法,也搞一个标记。最后一遍前缀和,结束。

我被这道题卡了很久的问题是一些细节没有处理好。一些边界少加一,多加一的。随后在自己手搓 hack 下,终于过掉啦啊。

#include <bits/stdc++.h> using namespace std; #define int long long const int N = 2e5+5; int n,t[N]; struct node{ int h,a; }a[N],c[N]; bool cmp(pair<int,bool> a,pair<int,bool> b){ if(a.first == b.first) return a.second > b.second; return a.first < b.first; } bool check(){ for(int i = 2;i <= n;i++) if(a[i].h<=a[i-1].h) return false; return true; } vector<pair<int,bool> > v; bool solve(){ v.clear(); //1为开始,0为结束。 cin >> n; for(int i = 1;i <= n;i++) { cin >> a[i].h; } for(int i = 1;i <= n;i++) { cin >> a[i].a; } for(int i = 1;i <= n;i++) { cin >> t[i]; } if(n==1){ cout<<0<<endl; return true; } for(int i = 1;i <= n;i++){ c[n-t[i]] = a[i]; } for(int i = 1;i <= n;i++){ a[i] = c[i]; } if(check()){ cout<<0<<endl; return true; } int res=0; for(int i = 2;i <= n;i++){ if(a[i-1].h > a[i].h) { if(a[i].a <= a[i-1].a) { return false; } v.push_back({((a[i-1].h - a[i].h) / (a[i].a-a[i-1].a) + 1),1}); }else if(a[i-1].h < a[i].h){ if(a[i].a >= a[i-1].a) v.push_back({0,1}); else { v.push_back({(a[i].h - a[i-1].h) % (a[i-1].a-a[i].a) == 0?(a[i].h - a[i-1].h) / (a[i-1].a-a[i].a):((a[i].h - a[i-1].h) / (a[i-1].a-a[i].a)+1),0}); res++; } }else{ if(a[i].a > a[i-1].a) v.push_back({0,1}); else return false; } } sort(v.begin(),v.end(),cmp); // for(auto it:v){ // cout<<it.first<<" "<<it.second<<endl; // } for(int it=0;it < v.size();it++){ if(v[it].second == 1) res++; else res--; if(res == n-1 && v[it+1].first != v[it].first) { cout<<v[it].first<<endl; return true; } } return false; } signed main(){ ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--){ if(!solve()) cout<<-1<<endl; } return 0; }

【USACO24JAN】Cu 复盘

T1

一开始我试着用双指针,但发现好像写不了。

后面发现恍然大悟。这道题我们可以手玩一定长度的数组。假设我们只有两种情况 1 代表的是相同数字的数,0 代表的是不同数字的数。

我们会发现只有形如 1,11,0,1 的子数组是最基础的形式,由这样可以变成 1,1,11,1,1,1 等知道填满数组,这样,就可以让所有的数字统一了。这也达到了目的。

所以我们只需要记录哪些数 ai=ai+1ai=ai+2。用 set 记录。

然后 set 自动排序和去重,直接输出即可。

但注意的是,你可能也有这样的经历!

你会觉得很逆天,但是“每一行后不能加空格”。这样,我们又愚蠢的把 set 转成 vector,判断是不是到末尾,是的话就不加空格。

话说 USACO 这波真的很逆天。

T2

我们发现直接模拟就好了,在 dfs 中,会有很多个参数。例如:

  • x 代表当前位置。
  • d 代表弹跳的力气。
  • f 代表方向。
  • cnt 代表砸烂了多少个。

我们对 dfs 进行剪枝即可。四个参数可以开一个数组来记忆化,但是空间会炸,所以开一个 map。

map<pair<pair<int,int>,pair<int,int> >,bool> mp;

这个记忆化只用记录是否走到,所以是一个 bool 类型。

这样,我们直接暴力模拟即可。轻松 AC!

T3

因为对于 i 进行操作,肯定会影响到后面的数,因此得先改前面的数再改后面的数,为了线性,不妨对 a 数组进行差分。

我们实时维护两个变量。

sum 数组是此时进行完操作后,之后会有多少增加细菌的个数。

然而 ans 维护的是答案,每一次会加上 di+sum 的绝对值。di 是差分数组。

时间复杂度 O(n)


__EOF__

本文作者gsczl71
本文链接https://www.cnblogs.com/gsczl71/p/17909469.html
关于博主:GDSZ初一蒟蒻,明年拿下七级勾
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   gsczl71  阅读(490)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示