2020暑期训练 week1

训练作息:

第一周,基本是 8:00-11:00 , 14:00 - 18:00 , 19:00 - 22:00


训练内容:

主要就是训练了5场比赛,4场cf,一场牛客


推荐题目:

E2. Asterism (Hard Version)

题目地址:https://codeforces.com/contest/1371/problem/E2
这题可以去看题解,我也是看官方题解写出来的https://codeforces.com/blog/entry/79624
首先要明白这个式子
在这里插入图片描述
其中bi表示的是整个序列中小于等于i的数的个数
当我们选第一个数时,肯定是要选小于等于x的数,即bx
第二个数,肯定要小于等于x+1,即bx+1,但是之前选走了一个数,所以只有bx+1 - 1种
以此类推,可得上式

设max为整个序列的最大值
x + n − 1 < m a x x+n-1<max x+n1<max时,携带的最大的都没有序列的最大值大,肯定不行,即f(x)=0 ,不满足
x ≥ m a x x\geq max xmax时,随便怎么选都可以,即f(x)=n!,也不满足
其他情况就是 m a x − n + 1 ≤ x < m a x max-n+1 \leq x<max maxn+1x<max
我们只需要满足
在这里插入图片描述
范围不超过2e5,所以我们可以直接记录i-bi的值,然后直接map找即可

int n,m;
char str[N];
int f[N];
unordered_map<int,int> mm;
int main()
{
    rr(n,m);
    FOR(i,1,n){
        r(f[i]);
    }
    sort(f+1,f+n+1);
    FOR(i,f[n]-n+1,f[n]+n-2){
        mm[i]=(i%m-(upper_bound(f+1,f+n+1,i)-f-1)%m+m)%m;
    }
    unordered_map<int,int> mmm;
    int st=max(0,f[n]-n+1);
    FOR(i,1,n-1){
        int now=st+i-1;
        mmm[mm[now]]++;
    }
    vector<int> ans;
    FOR(i,st,f[n]-1){
        mmm[mm[i+n-1]]++;
        if(mmm.count(i%m)&&mmm[i%m]>0){
//            cout<<i<<endl;
        }
        else{
            ans.pb(i);
        }
        mmm[mm[i]]--;
    }
    cout<<ans.size()<<endl;
    for(int x:ans){
        cout<<x<<' ';
    }
    cout<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值