模拟赛25

模拟赛25

最近怎么狂挂不止。

  1. 博弈

    考虑策略,首先是优先最小的,但是由于有重复的,所以在最小个数为偶数时会败,以此类推,可以想到当有一个数出现次数时奇数先手必胜,否则必败。

    考虑将相同的两两相消,发现 uvuv 是等价的。

    于是每个点维护一下当前的数,问题变成了求和当前集合相同的集合有几个,因为两两相消,可以异或 hash,也可用一些奇怪 hash。

    但是千万千万不要直接用 an,这个东西竟然是可以稳定被卡的!

  2. 跳跃

    发现其一定是在一个最大子段中反复横跳,然后在到下一个。

    数据比较水,错解轻松过(于是加了 hack)。

    hack 思路:

    首先是 kmin 的乱搞,这个轻松卡,就是 1,100000,100000,100000,100000 之类的用长段的负数让你一直在最前面跳,但其是可以到后面。

    这个在大数据随机下效果一般,不到 100 组就会出错,钦定第一个是 1 以后十几组就卡掉了。

    然后是一些假了的贪心,就是每次直接向最后一个可以跳到的地方跳,这个原理就是构造前后和的差距不大,但是从前面跳到后面会有较大代价导致不优,像 99999,100000,100000,100000,100000,99998,100000,100000k 比较小的时候。

    这个在小数据随机下效果一般,n,k20 时十几组就卡了(值域开大点),但是有人数据点分治但 n,k20dfs T 了没绷住。

    然后有一些逆天的 0,比如 k=0,有的要写特判。

    还有一些暴力会在恰好整除时错,懒得卡了,暴力一般也过不去。

    给一下数据生成器,多生成几组就有了
    #include<bits/stdc++.h>
    using namespace std;
    using llt=long long;
    using llf=long double;
    using ull=unsigned long long;
    #ifdef LOCAL
    FILE *InFile=freopen("in_out/in.in","r",stdin),*OutFile=freopen("in_out/in.in","w",stdout);
    #else
    FILE *InFile=stdin,*OutFile=stdout;
    #endif
    mt19937 rnd(ull(new char)*ull(new char));
    int main(){
    ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
    cout<<10<<endl;
    for(int t=1;t<=10;++t){
    int k=rnd()%10+1;
    if(k<=2){
    int n=901+rnd()%100,k=999999901+rnd()%100; cout<<n<<' '<<k<<endl;
    for(int i=1;i<=n;++i){
    if(rnd()%5==0) cout<<0<<' ';
    else cout<<int(rnd()%200000)-100000<<' ';
    }cout<<endl;
    }else if(k<=4){
    int n=901+rnd()%100,k=999999901+rnd()%100; cout<<n<<' '<<k<<endl;
    cout<<1<<' '; for(int i=2;i<=n;++i) cout<<int(rnd()%200000)-100000<<' '; cout<<endl;
    }else if(k<=6){
    int n=10+rnd()%10,k=10+rnd()%10; cout<<n<<' '<<k<<endl;
    for(int i=1;i<=n;++i) cout<<int(rnd()%200000)-100000<<' '; cout<<endl;
    }else if(k<=8){
    int n=rnd()%1000+1,k=rnd()%1000000000+1; cout<<n<<' '<<k<<endl;
    for(int i=1;i<=n;++i) cout<<int(rnd()%200000)-100000<<' '; cout<<endl;
    }else{
    int n=rnd()%1000+1; cout<<n<<' '<<0<<endl;
    for(int i=1;i<=n;++i) cout<<int(rnd()%200000)-100000<<' '; cout<<endl;
    }
    }
    }
  3. 大陆

    水题,建议改名:树分块前置。

    就是考虑维护子树中没有被选的,合并到父亲上,如果 B 就单开一个,以父节点为省会。

    最后的根直接归到最后一个即可,可以证明其不超过 3B1

  4. 排列

    逆天题。

    其实思路很简单,就是直接维护 minmax,在子树是否存在三元组,二元组中最大的最小和最小的最大。

    因为只有在不存在三元组时要维护二元组,直接子树二分即可。

    代码长,但还算好写。

posted @   5k_sync_closer  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示