由于学校要求,过来打 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'}\) 种方案;这个不会影响后续插入时对方案数的分析,因为任意一个被删除的路径下面之后也不能再有路径了

于是答案即为

\[\prod_{i=1}^{N-1}\begin{cases}\binom{A_i-1}{A_{i-1}-1}&(A_i>A_{i-1})\\\binom{A_{i-1}}{A_i}&(A_i\le A_{i-1})\end{cases}
\]

总复杂度 \(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游记的更多相关文章

  1. 【20161203-20161208】清华集训2016滚粗记&&酱油记&&游记

    先挖坑(这个blog怎么变成游记专用了--) 已更完 #include <cstdio> using namespace std; int main(){ puts("转载请注明 ...

  2. 【20160722-20160728】NOI2016滚粗记&&酱油记&&游记

    先挖坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs.c ...

  3. NOIp2016 游记

    DAY -2 不要问我为什么现在就开了一篇博客. 本来想起个NOIp2016爆零记或者NOIp2016退役记之类的,但是感觉现在不能乱立flag了.所以就叫游记算了. 前几场模拟赛崩了一场又一场,RP ...

  4. NOIP2016游记

    只是游记而已.流水账. Day0:忘了. Day1:看完T1,本以为T2一如既往很简单,结果看了半天完全没有思路.然后看了一眼T3,期望,NOIP什么时候要考期望了,于是接着看T2.一开始我推的限制条 ...

  5. CTSC2016&&APIO2016滚粗记&&酱油记&&游记<del>(持续更新)</del>

    挖一波坑 #include <cstdio> using namespace std; int main(){ puts("转载请注明出处:http://www.cnblogs. ...

  6. 游记——noip2016

    2016.11.18 (day 0) 呆在家. 悠闲地呆在家.. 明后天可能出现的错误: 1)没打freopen.打了ctime: 2)对拍程序忘记怎么写了...忘记随机化种子怎么写了: 3)不知道厕 ...

  7. 【NOIP 2015 & SDOI 2016 Round1 & CTSC 2016 & SDOI2016 Round2】游记

    我第一次写游记,,,, 正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪里?正文在哪 ...

  8. ZJOI2016二试+游记

    ...excited.... 一场打回原形爽哦. T1莫名爆到了10分,T2T3均没交,一个小时过后就没再拿任何分数,perfectly狗带了... 总之没有给自己充足的时间去敲暴力,ZJOI啊..拿 ...

  9. NOIP2015游记——一次开心又失望的旅行

    啊,一年一度的NOIP终于是结束了 以前的大神都有写自己的感受 然而我居然给忘了!!!! 吓得我赶紧来写一份游记 Day.-INF--出发前一个星期 机智的我选择了停课 就是为了OIER这伟大而又光荣 ...

  10. CTSC2017 && APIO2017 && THUSC2017 游记

    一去北京就是近20天,还是回来写写游记吧. 5.6 坐飞机到天津转动车到北京. 5.7 在天坛公园逛了一圈就去报到了. 下午试机,好像没发生什么. 5.8 CTSC一试 T1签到,开个桶打个标记就好了 ...

随机推荐

  1. 记一次 .NET 某工控MES程序 崩溃分析

    一:背景 1.讲故事 前几天有位朋友找到我,说他的程序出现了偶发性崩溃,已经抓到了dump文件,Windows事件日志显示的崩溃点在 clr.dll 中,让我帮忙看下是怎么回事,那到底怎么回事呢? 上 ...

  2. JavaScript:this指针

    this指针,存储的是一个内存地址,如同变量一样,指向一块内存区域: 而这个内存区域,保存的就是一个对象的数据,那么这个对象是什么呢? 通常来说,this指针,主要是用在方法(函数)中,用来指向调用方 ...

  3. 【转载】EXCEL VBA-区域选择

    1- 区域命名 ThisWorkbook.Names.Item("foo").RefersTo =Tabelle1!$A$1:$B$1 ThisWorkbook.Names.Ite ...

  4. MongoDB从入门到实战之Docker快速安装MongoDB

    前言 在上一篇文章中带领带同学们快速入门MongoDB这个文档型的NoSQL数据库,让大家快速的了解了MongoDB的基本概念.这一章开始我们就开始实战篇教程,为了快速把MongoDB使用起来我将会把 ...

  5. python进阶之路4基本运算符、格式化输出

    内容回顾 PEP8规范 代码编写规范及美观 python注释语法 平时养成写注释的习惯 1.警号 2.三个单引号 3.三个双引号 常量与变量 1.变量语法结构 变量名 赋值符合 数据值 2.底层原理 ...

  6. Zabbix与乐维监控对比分析(八)——其他功能篇

    前面我们详细介绍了Zabbix与乐维监控的架构与性能.Agent管理.自动发现.权限管理.对象管理.告警管理.可视化.图形图表及网络功能方面的对比分析,接下来我们将对二者其他功能进行对比分析. 本篇是 ...

  7. 第三方模块的下载与使用 requests模块 openpyxl模块

    今日内容 第三方模块下载操作 第三方模块: 别人写的魔魁啊 一般情况下都很强大 python中模块很多 如果想使用第三方模块 第一次必须先下载 后面就可以反复使用 =内置模块 下载第三方模块的方式: ...

  8. Python 跨模块使用全局变量(自定义类型)

    gol.py def _init():#初始化 global _global_dict _global_dict = {} def set_value(key,value): "" ...

  9. win32com操作word 第三集:Range精讲(一)

    本课程<win32com操作word API精讲&项目实战>,本公众号以文字分享为主,B站与视频号则发布视频分享,ID均为:一灯编程 本集开始,将会深入Document接口.打开或 ...

  10. 基于 VScode 搭建 Qt 运行环境

    插件 C/C++ Qt tools Qt Configure CMake CMake Tools 下载 qt https://download.qt.io/official_releases/onli ...