首页 > 其他分享 >USACO2023Jan游记

USACO2023Jan游记

时间:2023-01-31 20:25:13浏览次数:67  
标签:index QAQ USACO2023Jan usaco uint freopen org 游记

由于学校要求,过来打 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

力不从心,打不起哩。

标签:index,QAQ,USACO2023Jan,usaco,uint,freopen,org,游记
From: https://www.cnblogs.com/myee/p/USACO2023Jan.html

相关文章

  • 游记 索引
    NOI2022邮寄FJOI2022游记2022WC比赛总结反思NOI2021同步赛打铁记&总结FJOI2021游记2021WC比赛总结反思APIO2020游记......
  • CTS 2023 游记【脱敏版】
    该版本删去了一些可能敏感的信息.2023.12.16前几天和戴老师聊天的时候想能不能给CTS投点题什么的,如果又全是Ynoi题就不好了呢.毕竟前段时间lxl[数据删除],这是......
  • 【游记】NOI WC 2023线上
    摸鱼记录Day1:那一天记得只有开幕式,开幕式确实十分无聊,几个人在那里上台讲话,又有几个人在那里上台表演,看完开幕式,我认为就是浪费了一个小时。不过今年是NOI40周年,看着那......
  • WC 2023 游记
    杭州集训还是比较震撼的。因为NOIP期间没啥条理的训练计划和焦急的心理,NOIP之后我的竞技状态一直不太行,简单的部分分因为想复杂想不出都是常态。后来找教练聊了下天,然后......
  • WC2023 游记
    Day-3~Day0听课记录会补的。zxy/ll。Day1想着自己打了这么多年OI了,三块铜牌一块银牌,未免太搞笑了点,觉得这场必须拿金。开考好像卡了,等了很久才把题目下下来。......
  • WC2023游记
    真的是游记Day0开幕式。感觉很受震撼。就是成都七中现场的大屏幕太宽了结果宣传片里的人全成杆子(不过期待半天的变脸真的看到了/cyDay1~3上课,听不懂,摆烂,完全不补题......
  • WC2023 游记
    Day0开幕式,随便听了听,好像没啥好玩的。Day1早上的课先开了第一课堂,发现非常抽象,完全听不懂,于是润第二课堂学了ddp。习武坐车回老家,所以在车上用手机听,然而听一半车......
  • 【游记】WC 2023 线上游记
    Day1看到WC竟然和期末考试冲突,但是谁让WC讲课我也听不懂就去考期末了。祝福可以考一个好成绩Day2依旧在考期末,第一天的期末考试真的要考寄了。Day3期末终于结......
  • CTS 2023 游记
    精神状态很好。Day-4早上五点就被喊醒,做了车到禄口机场,结果经典晕车,刚到门口就吐了一波胃酸/tuu。坐飞机刚刚感觉还好,起飞不是很晕,但到后来感觉越来越晕,不知道是N95......
  • WC2023 游记
    不是很会写游记,随便写写吧。一些附件讲课资料合集(压缩后\(\rm31MB\))太大了,可以去U群下载。由于后面很多乐子,我把相关内容打包成zip上传上来了。乐子合集下载链接......