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签到,开个桶打个标记就好了 ...
随机推荐
- STL list容器API
list容器:链表容器,不支持随机遍历.不能用通用的sort算法(要有随机访问迭代器),容器自己有排序算法 #define _CRT_SECURE_NO_WARNINGS #include<io ...
- 8、IDEA提交代码出现: Fetch failed fatal: Could not read from remote repository
转载自 第一步.确认Git公钥/密钥是否生成: 1. 首先查看本地是否生成git密钥,一般在C盘home目录下:[C:你自己的home目录\.ssh] 第二步:添加Git密钥: 右键->Git ...
- CH334、CH335USB2.0Hub芯片(更新ing)
USB HUB又称USB集线器,主要用于USB主机端口扩展,广泛应用于计算机,笔记本,及周边应用.CH334.CH335是符合 USB2.0 协议规范的高性能MTT 4 端口 USB2.0 HUB ...
- 2021 & 2022年终回顾:山河无恙,烟火寻常
前言 又到了一年一度年终回顾的时候了,回想起去年年底圣诞节的时候由于忙着参加黑客松大赛,一下子就进入了新的一年,失去了年终回顾的动力,所以今年提前两个月开始进行回顾,这样的话今年最后一天就可以顺利发文 ...
- .Net 6 使用 Consul 实现服务注册与发现 看这篇就够了
前言 在这几年的工作中,也经历过几个微服务项目,大多数都上了k8s,基本上都看不到Consul的身影,所以在工作之余折腾了下Consul,作为个人来讲还是得学习下,所以也就顺便通过文章来记录下学习过程 ...
- 数据预处理时为什么要使用OneHot编码?
什么是LabelEncoder(整数编码) 整数编码 将一列文本数据转化成数值,即列中的每一个特征都通过一个整数来表示.例如,[red, blue, red, yellow] = [0,2,0,1]. ...
- 疯狂吐槽 MAUI 以及 MAUI 入坑知识点
目录 窗口 窗口管理 如何限制一次只能打开一个程序 MAUI 程序安装模式 为 MAUI Blazor 设置语言 坑 ① 坑 ② 坑 ③ 配置 MAUI 项目使用管理员权限启动 问题背景 定制编译过程 ...
- 使用SQL获取当前周别,oracle日期处理
使用SQL获取当前周别 select to_char(sysdate,'yyyyww') from dual select to_char(to_date('20200611','yyyymmdd' ...
- angular打包部署设置publicPath文件目录及访问地址,解决打包完成后,运行打包文件,报错404,js,css未找到
方案1.改变文件目录 不改变访问地址:XXXPRO 是部署的服务器上面的 文件夹名称 ng build --prod --base-href /XXXPRO 方案2.改变访问地址录同时改变文件目录-- ...
- Stream流中的常用方法_skip-Stream流中的常用方法_concat
Stream流中的常用方法_skip 如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流∶ 如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流.基本使用: Strea ...