USACO2023Jan游记
由于学校要求,过来打 USACO。
似乎要求起码升到白金?
由于是第一次打,只有从铜组开始了。
Brouze
简单题,就给核心代码。
30min AK。
Leaders
http://usaco.org/current/index.php?page=viewproblem&cpid=1263
chr C[100005];uint R[100005];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint n;scanf("%u%s",&n,C);for(uint i=0;i<n;i++)scanf("%u",R+i);
chr c=*C;uint p=0;while(C[p]==c)p++;
uint ans=0;for(uint i=0;i<p;i++)ans+=R[i]>p;
bol ok=R[0]==p;for(uint i=p;i<n;i++)ok&=C[i]!=c;
ans+=ok;
printf("%u\n",ans);
return 0;
}
Air Cownditioning II
http://usaco.org/current/index.php?page=viewproblem&cpid=1264
uint L[25],R[25],C[25],A[25],B[25],P[25],M[25],Cnt[105];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint n,m;scanf("%u%u",&n,&m);
for(uint i=0;i<n;i++)scanf("%u%u%u",L+i,R+i,C+i),L[i]--;
for(uint i=0;i<m;i++)scanf("%u%u%u%u",A+i,B+i,P+i,M+i),A[i]--;
uint ans=-1;
for(uint i=0;i<(1u<<m);i++){
for(uint i=0;i<100;i++)Cnt[i]=0;
uint wil=0;
for(uint j=0;j<m;j++)if(i>>j&1){
wil+=M[j];for(uint k=A[j];k<B[j];k++)Cnt[k]+=P[j];
}
bol ok=1;
for(uint j=0;j<n;j++)for(uint k=L[j];k<R[j];k++)ok&=Cnt[k]>=C[j];
if(ok)_min(ans,wil);
}
printf("%u\n",ans);
return 0;
}
Moo Operations
http://usaco.org/current/index.php?page=viewproblem&cpid=1265
chr C[105];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint t;scanf("%u",&t);
while(t--){
uint n=0;scanf("%s",C);while(C[n])n++;
uint ans=-1;
for(uint i=1;i+1<n;i++)if(C[i]=='O')
_min(ans,n-1-(C[i-1]=='M')-(C[i+1]=='O'));
printf("%d\n",(int)ans);
}
return 0;
}
Silver
1h30min AK。
Find and Replace
http://usaco.org/current/index.php?page=viewproblem&cpid=1266
恶心的题目,做了 1h。
基环树和环的答案是不同的!!!
由于只能变字母,要特判 \(52\rightarrow52\) 的全环情况!!!
chr A[100005],B[100005],To[128];
bol Gone[128];
voi solve(){
for(uint i=0;i<=127;i++)Gone[i]=0;
uint ans=0;scanf("%s%s",A,B);
for(uint i=0;A[i];i++){
if(!Gone[(uint)A[i]])To[(uint)A[i]]=B[i],Gone[(uint)A[i]]=1,ans+=A[i]!=B[i];
if(To[(uint)A[i]]!=B[i]){puts("-1");return;}
}
if(ans){
std::set<uint>S1,S2;
for(uint c=0;c<=127;c++)if(Gone[c])S1.insert(c),S2.insert(To[c]);
if(S1.size()==52&&S2.size()==52){puts("-1");return;}
for(uint c:S1)if((uint)To[c]==c)Gone[c]=false;
for(uint p:S1)if(Gone[p]&&!S2.count(p)){
std::vector<uint>V;
while(Gone[p])Gone[p]=false,V.push_back(p),p=To[p];
}
for(uint p:S1)if(Gone[p]&&S2.count(p)){
std::vector<uint>V;
while(Gone[p])Gone[p]=false,V.push_back(p),p=To[p];
for(auto s:V)if(s==p)ans++;
}
}
printf("%u\n",ans);
}
Following Directions
http://usaco.org/current/index.php?page=viewproblem&cpid=1267
注意到形成树的结构,直接记录每个子树大小即可。
线段树分治可以做,但没有必要。
chr C[2005][2005];
uint R[2005],D[2005];
uint V[2005][2005];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint n,q;scanf("%u",&n);
for(uint i=0;i<n;i++)scanf("%s%u",C[i],R+i);
for(uint i=0;i<n;i++)scanf("%u",D+i);
for(uint i=0;i<n;i++)for(uint j=0;j<n;j++)V[i][j]=1;
for(uint i=0;i<n;i++)for(uint j=0;j<n;j++)(C[i][j]=='R'?V[i][j+1]:V[i+1][j])+=V[i][j];
uint sum=0;
for(uint i=0;i<n;i++)sum+=V[i][n]*R[i]+V[n][i]*D[i];
printf("%u\n",sum);
scanf("%u",&q);
while(q--){
uint x,y;scanf("%u%u",&x,&y),x--,y--;
for(uint i=x,j=y;;){
C[i][j]=='R'?j++:i++,V[i][j]-=V[x][y];
if(i==n){sum-=V[x][y]*D[j];break;}
if(j==n){sum-=V[x][y]*R[i];break;}
}
C[x][y]^='R'^'D';
for(uint i=x,j=y;;){
C[i][j]=='R'?j++:i++,V[i][j]+=V[x][y];
if(i==n){sum+=V[x][y]*D[j];break;}
if(j==n){sum+=V[x][y]*R[i];break;}
}
printf("%u\n",sum);
}
return 0;
}
Moo Route
http://usaco.org/current/index.php?page=viewproblem&cpid=1268
画个图就做完了。
uint A[100005];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint n;scanf("%u",&n);
for(uint i=0;i<n;i++)scanf("%u",A+i),A[i]--;
for(uint p=0;A[p];)
{
while(!p||A[p]>A[p-1])--A[p++],putchar('R');
while(p&&A[p-1])--A[--p],putchar('L');
}
for(uint i=0;i<n;i++)putchar('L');
putchar('\n');
return 0;
}
Gold
2h AK。
Find and Replace
http://usaco.org/index.php?page=viewproblem&cpid=1269
考虑动态维护每个串的每个字母会被哪个规则替换,则加入一条新规则时,其将作用于之前所有未被替换的某个字母。
这个可以拿 \(26\) 个 vector
直接维护。
记录下来后,整个结构是一张 DAG,把每个串串长记录下来即可。
然后如果直接在 DAG 上 dfs,很容易卡到 \(O(nq)\)(\(n\) 表示查询区间长度):
1 200000 200000
a aa
a aa
a aa
a aa
...
a aa
a b
b a
a b
b a
...
b a
这个东西每找一个字符都会跑满整一层,不优。
考虑在 DAG 的每个节点处,若其对应串长不超过 \(B\),则把其整个字符串记录下来。
查询时如果串长不超过 \(B\),就不再往下递归,直接输出这段区间。
容易分析这样的总复杂度为 \(O(q(B+\frac nB))\),取 \(B=\sqrt n\),得复杂度为 \(O(q\sqrt n)\)。
由于这个东西非常跑不满,直接取 \(B=20\) 即可通过。
(当然也不排除可以进一步分析出 \(O(q(B+\frac n{B^2}))\) 等更紧的界,因为我会构造的最坏数据只能达到这个复杂度级别,那样的平衡复杂度就是 \(O(q\ {}^3\!\!\!\!\sqrt n)\))
std::vector<std::pair<uint,uint> >Find[26];
std::vector<chr>S[200005],S2[200005];
std::vector<uint>To[200005];
chr C[200005];
ullt Len[200005];
voi dfs(uint q,ullt l,ullt r){
if(S2[q].size()){
for(uint i=l;i<r;i++)putchar(S2[q][i]);
return;
}
for(uint i=0;i<To[q].size()&&l<r;i++)
if(~To[q][i])
if(l<Len[To[q][i]])
if(r<=Len[To[q][i]])dfs(To[q][i],l,r),l=r=0;
else dfs(To[q][i],l,Len[To[q][i]]),r-=Len[To[q][i]],l=0;
else r-=Len[To[q][i]],l-=Len[To[q][i]];
else
{
if(!l)putchar(S[q][i]);else l--;
r--;
}
}
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
ullt l,r;uint q;scanf("%llu%llu%u",&l,&r,&q);
S[0]={'a'},To[0]={-1u},Find[0].push_back({0,0});
for(uint i=1;i<=q;i++){
scanf("%s",C);for(auto s:Find[*C-'a'])To[s.first][s.second]=i;
Find[*C-'a'].clear(),scanf("%s",C);
for(uint j=0;C[j];j++)S[i].push_back(C[j]),Find[C[j]-'a'].push_back({i,j});
To[i].resize(S[i].size(),-1);
}
for(uint i=q;~i;i--){
for(uint j=0;j<To[i].size();j++)
if(~To[i][j])_min(Len[i]+=Len[To[i][j]],2000000000000000000llu);
else _min(++Len[i],2000000000000000000llu);
if(Len[i]<=20)for(uint j=0;j<To[i].size();j++){
if(~To[i][j])S2[i].insert(S2[i].end(),S2[To[i][j]].begin(),S2[To[i][j]].end());
else S2[i].push_back(S[i][j]);
}
}
dfs(0,l-1,r),putchar('\n');
return 0;
}
Lights Off
http://usaco.org/index.php?page=viewproblem&cpid=1270
感觉题目里给的这个 move 操作很奇怪,数据范围也很怪(\(n\) 很小但 \(T\) 很大),时限也给了 \(4s\),考虑大胆猜结论:答案很小,是 \(O(n)\) 或者类似的级别,可以暴力枚举;但是信息的预处理复杂度与 \(2^n\) 有关。
考虑把对答案的贡献拆分,发现操作了 \(a\) 步时,原有的开关串会带来其旋转 \(0,1,2,\dots,a-1\) 步后的结果的贡献,自己扭动的开关会带来长度为 \(1,2,3,\dots,a\) 的连续 \(1\) 的贡献。
我们由于在暴力枚举答案,前面的贡献容易直接算掉,考虑判断剩下部分的贡献是否可以用由长度为 \(1,2,3,\dots,a\) 的连续 \(1\) 的贡献异或而成。
这个东西我们考虑 dp 预处理,设 \(f_{a,v}=\tt true\) 表示 \(v\) 可以由长度为 \(1,2,3,\dots,a\) 的连续 \(1\) 的贡献异或而成,反之则不能。
容易有一个 \(O(na2^n)\) 复杂度的 dp。
把 \(a\) 取遍 \(0\sim n\) 甚至 \(0\sim n+5\),把结果打个表观察一下,容易发现,\(k>n/2\) 时总有 \(f_{k,v}=f_{k+4,v}\)。
证明感觉很复杂,我不会证,但是我把 \(n=2,\dots,20\) 中随机取了几个验证了一下,似乎都是对的。那就当做这是对的吧。
因此 \(a\) 更大的时候可以直接调用 \(a\) 很小的值,于是直接把 \(a\) 预处理到 \(n/2+4\) 是可行的!
总复杂度不会分析,但是应该是 \(O(n^22^n+Tn)\) 的,实测可以通过。
uint n;chr C[25];
bol Ok[21][1u<<20|1];
inline uint nxt(uint v){return(v<<1&((1u<<n)-1))|(v>>(n-1)&1);}
voi solve(){
uint a=0,b=0;
scanf("%s",C);for(uint i=0;i<n;i++)a|=(C[i]=='1')<<i;
scanf("%s",C);for(uint i=0;i<n;i++)b|=(C[i]=='1')<<i;
uint ans=0;
while(!Ok[ans<=n/2?ans:(ans-n/2-1)%4+n/2+1][a])ans++,a^=b,b=nxt(b);
printf("%u\n",ans);
}
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
uint t;scanf("%u%u",&t,&n);
Ok[0][0]=1;
for(uint i=1,v=1,t=1;i<=n/2+4;i++,v^=t=nxt(t))
for(uint t=0;t<n;t++,v=nxt(v))for(uint j=0;j<(1u<<n);j++)
Ok[i][j]|=Ok[i-1][j^v];
// for(uint i=1;i<=n/2+4;i++,putchar('\n'))
// for(uint j=0;j<(1u<<n);j++)
// putchar('0'+Ok[i][j]);
while(t--)solve();
return 0;
}
Moo Route
http://usaco.org/index.php?page=viewproblem&cpid=1271
银组对应题目的计数版本!
把 \(a\) 除二,仅仅考虑向右的路径。
显然我们可以把向右的路径自上而下排成一排,使得上一行的右端点大于下一行的左端点。
对这些路径从左往右扫描,当前列应当剩下恰好 \(a\) 条路径。
假设扫描过程中某一步 \(a\) 变成了 \(a'\)。
当 \(a'>a\) 时,你要在之前的路径基础上增加 \(a'-a\) 条,并且均放在之前的某些路径的下面,方案数为 \(\binom{a'-1}{a-1}\);之所以不能放在最上面一条路径的上面,是因为上一行的右端点应大于下一行的左端点。
当 \(a'\le a\) 时,你要从之前的路径中选出 \(a'\) 条留下,其余的删除,有 \(\binom a{a'}\) 种方案;这个不会影响后续插入时对方案数的分析,因为任意一个被删除的路径下面之后也不能再有路径了。
于是答案即为
\]
总复杂度 \(O(T)\)。(其中 \(T=\sum A\))
(从某种角度上来看,这种做法其实质是构造了一个双射)
const ullt Mod=1e9+7;
typedef ConstMod::mod_ullt<Mod>modint;
typedef std::vector<modint>modvec;
modint P[4000005],Q[4000005];
uint A[100005];
int main()
{
#ifdef MYEE
freopen("QAQ.in","r",stdin);
// freopen("QAQ.out","w",stdout);
#endif
P[0]=1;for(uint i=1;i<=4000000;i++)P[i]=P[i-1]*i;
Q[4000000]=P[4000000].inv();for(uint i=4000000;i;i--)Q[i-1]=Q[i]*i;
uint n;scanf("%u",&n);for(uint i=0;i<n;i++)scanf("%u",A+i),A[i]>>=1;
// modint ans=Q[A[0]]*P[A[0]-1];
modint ans=1;
for(uint i=1;i<n;i++)
if(A[i]<=A[i-1])ans*=P[A[i-1]]*Q[A[i]]*Q[A[i-1]-A[i]];
else ans*=P[A[i]-1]*Q[A[i-1]-1]*Q[A[i]-A[i-1]];
ans.println();
return 0;
}
Platinum
力不从心,打不起哩。
USACO2023Jan游记的更多相关文章
- 【20161203-20161208】清华集训2016滚粗记&&酱油记&&游记
先挖坑(这个blog怎么变成游记专用了--) 已更完 #include <cstdio> using namespace std; int main(){ puts("转载请注明 ...
- 【20160722-20160728】NOI2016滚粗记&&酱油记&&游记
先挖坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.c ...
- NOIp2016 游记
DAY -2 不要问我为什么现在就开了一篇博客. 本来想起个NOIp2016爆零记或者NOIp2016退役记之类的,但是感觉现在不能乱立flag了.所以就叫游记算了. 前几场模拟赛崩了一场又一场,RP ...
- NOIP2016游记
只是游记而已.流水账. Day0:忘了. Day1:看完T1,本以为T2一如既往很简单,结果看了半天完全没有思路.然后看了一眼T3,期望,NOIP什么时候要考期望了,于是接着看T2.一开始我推的限制条 ...
- CTSC2016&&APIO2016滚粗记&&酱油记&&游记<del>(持续更新)</del>
挖一波坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs. ...
- 游记——noip2016
2016.11.18 (day 0) 呆在家. 悠闲地呆在家.. 明后天可能出现的错误: 1)没打freopen.打了ctime: 2)对拍程序忘记怎么写了...忘记随机化种子怎么写了: 3)不知道厕 ...
- 【NOIP 2015 & SDOI 2016 Round1 & CTSC 2016 & SDOI2016 Round2】游记
我第一次写游记,,,, 正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪 ...
- ZJOI2016二试+游记
...excited.... 一场打回原形爽哦. T1莫名爆到了10分,T2T3均没交,一个小时过后就没再拿任何分数,perfectly狗带了... 总之没有给自己充足的时间去敲暴力,ZJOI啊..拿 ...
- NOIP2015游记——一次开心又失望的旅行
啊,一年一度的NOIP终于是结束了 以前的大神都有写自己的感受 然而我居然给忘了!!!! 吓得我赶紧来写一份游记 Day.-INF--出发前一个星期 机智的我选择了停课 就是为了OIER这伟大而又光荣 ...
- CTSC2017 && APIO2017 && THUSC2017 游记
一去北京就是近20天,还是回来写写游记吧. 5.6 坐飞机到天津转动车到北京. 5.7 在天坛公园逛了一圈就去报到了. 下午试机,好像没发生什么. 5.8 CTSC一试 T1签到,开个桶打个标记就好了 ...
随机推荐
- python Flask 操作数据库
Flask数据库 转载:Flask数据库 - 苦行僧95 - 博客园 (cnblogs.com) Flask-SQLAlchemy Flask-SQLAlchemy是在Flask中操作关系型数据库的拓 ...
- [OpenCV实战]50 用OpenCV制作低成本立体相机
本文主要讲述利用OpenCV制作低成本立体相机以及如何使用OpenCV创建3D视频,准确来说是模仿双目立体相机,我们通常说立体相机一般是指双目立体相机,就是带两个摄像头的那种(目就是指眼睛,双目就是两 ...
- [常用工具] OpenCV_contrib库在windows下编译使用指南
本文主要讲述opencv及opencv_contrib库在windows下基于vs2017编译安装指南.所用OpenCV版本为OpenCV4.4,编译平台为vs2017. 文章目录 1 下载 2 编译 ...
- Mybatis用List接收返回值
Mybatis 用 List 接收返回值 以 List<Map<String, Object>> 为例 1.XML内 resultType 为单条记录对应类型,设置成 java ...
- [WPF]限制程序单例运行
代码 System.Threading.Mutex mutex; protected override void OnStartup(StartupEventArgs e) { bool ret; m ...
- 算法之Dijkstra及其堆优化和SPFA:图上单源最短路径神器
签到题-- 题目传送门 SPFA算法 本人曾经写过一篇有关Bellman-ford的博,但就算是挂了优化的ford也只能过这道题的弱化版. 今天就先填个坑,先讲SPFA. 在这里我直接认为你们已经有一 ...
- linux环境编程(1): 实现一个单元测试框架
写在前面 在开发的过程中,大多数人都需要对代码进行测试.目前对于c/c++项目,可以采用google的gtest框架,除此之外在github上搜索之后可以发现很多其他类似功能的项目.但把别人的轮子直接 ...
- WeetCode4 —— 二叉树遍历与树型DP
一丶二叉树的遍历 1.二叉树遍历递归写法与递归序 了解过二叉树的朋友,最开始肯定是从二叉树的遍历开始的,二叉树遍历的递归写法想必大家都有所了解. public static void process( ...
- Grafana 系列文章(三):Tempo-使用 HTTP 推送 Spans
️URL: https://grafana.com/docs/tempo/latest/api_docs/pushing-spans-with-http/ Description: 有时,使用追踪系统 ...
- 【一句话】@Configuration和@Component的区别
首先一句话: @Configuration修饰的类会被Cglib动态代理,@Component不会. 详细: Cglib动态代理生成当前对象的子类Class,并对方法拦截,多次调用@Bean方法时直接 ...