Codeforces Round 977 (Div. 2, based on COMPFEST 16 - Final Round)

致敬传奇调题王 HDK

本场最难崩评论

A.Meaning Mean

给定一个序列 a,每次选择 i,j (ij),使得其缩成一个值为 ai+aj2 的数,直至剩余一个数,求最终答案的最大值

一开始想的是最小化 ai+aj2 的损失,后来发现这点损失基本上可以不管,因为最后的值一定可以表示成 ai+aj+22 的形式,可以近似看成 ai×21+aj×22×,最大化其值也即将最大值放在前面,贪心即可

#define int long long
int n;
int a[100001];
bool vis[100001];
signed main(){
    int cases;cin>>cases;while(cases--){
        cin>>n;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            vis[i]=false;
        }
        int cnt=0;
        sort(a+1,a+n+1);
        int ans=(a[1]+a[2])/2;
        for(int i=3;i<=n;++i){
            ans=(ans+a[i])/2;
        }
        cout<<ans<<'\n';
    }
}

B.Maximize Mex

给定一个序列 a 与一个数 x,可以进行如下操作

  • 选择任意一个 i,使得 ai 自增 x

最大化其 mex

发现一个 ai 只能由满足 ajai(modx)ajaij 转移得到

因此对 aimodx 开桶,求 mex 肯定是枚举自然数,ajai 的条件可以通过每次转移完再放进桶里来实现,每次从桶里拿一个出来填 mex

#define int long long
int n,x;
int a[200001];
int cnt[200001];
int remaincnt[200001];
signed main(){
    int cases;cin>>cases;while(cases--){
        cin>>n>>x;
        memset(cnt,0,sizeof cnt);
        memset(remaincnt,0,sizeof remaincnt);
        for(int i=1;i<=n;++i){
            cin>>a[i];
            if(a[i]>n) continue;
            cnt[a[i]]++;
        }
        bool flag=false;
        for(int i=0;i<=n;++i){
            if(cnt[i]==0){
                if(remaincnt[i%x]==0){
                    cout<<i<<'\n';
                    flag=true;
                    break;
                }
                remaincnt[i%x]--;
            }
            else{
                cnt[i]--;
            }
            remaincnt[i%x]+=cnt[i];
        }
    }
}

C2.Adjust The Presentation (Hard Version)

发现问题可以转化成 “a 中的元素在 b 中第一次出现的位置是否升序排列”,因为你会发现元素只有第一次出现的位置有关系,如果一个元素已经出现过一次,那么总会能够灵活地插入到它下一次应该出现的位置上,这也就意味着,如果一个元素已经出现过,那么它就与答案无关了

所以一个线性的 check 就出来了,统计 a 中每个元素在 b 中第一次出现的位置,判断是否升序排列

然而复杂度不够优秀,考虑加入一个 cnt 统计当前有多少不满足升序排列的数对,显然 cnt=0 时合法

对值域上每一个元素开一个 set,记录其所有出现的位置,这样插入与删除位置,查询最小值都是 log 的,我们就可以快速维护元素第一次出现的位置

然后让 cnt 减去修改前,修改位置旁边的不合法对数,加上修改后的对数,只统计修改位置旁边的是因为只有这些值可能会改变

需要注意的

  • 特判修改位置为 1n 的情况
  • 如果被修改位置和目标位置在值域上离得太近,比如 AB=1,那么要留神是不是将 (A,B)(B,A) 全都统计进答案里了,然而这是错误的
#define int long long
int n,m,q;
int a[200001],b[200001];
int pos[200001];
set<int>o_pos[200001];
int unsucc_cnt=0;
void check(){
    for(int i=1;i<=n-1;++i){
        if(*o_pos[a[i]].begin()>=*o_pos[a[i+1]].begin()) unsucc_cnt++;
    }
}
signed main(){
    ios::sync_with_stdio(false);
    int cases;cin>>cases;while(cases--){
        cin>>n>>m>>q;
        unsucc_cnt=0;
        for(int i=1;i<=n;++i){
            cin>>a[i];
            pos[a[i]]=i;
            o_pos[i].clear();
        }
        for(int i=1;i<=m;++i){
            cin>>b[i];
            o_pos[b[i]].insert(i);
        }
        for(int i=1;i<=n;++i){
            o_pos[a[i]].insert(m+n+pos[a[i]]);
        }
        check();
        cout<<(unsucc_cnt==0?"YA":"TIDAK")<<'\n';
        while(q--){
            int x,y;
            cin>>x>>y;
            int uncnt1=0,uncnt2=0;
            if(pos[b[x]]!=1 and *o_pos[a[pos[b[x]]-1]].begin()>=*o_pos[b[x]].begin()) uncnt1++;
            if(pos[b[x]]!=n and *o_pos[b[x]].begin()>=*o_pos[a[pos[b[x]]+1]].begin()) uncnt1++;
            if(pos[y]!=1 and a[pos[y]-1]!=b[x] and *o_pos[a[pos[y]-1]].begin()>=*o_pos[y].begin()) uncnt1++;
            if(pos[y]!=n and a[pos[y]+1]!=b[x] and *o_pos[y].begin()>=*o_pos[a[pos[y]+1]].begin()) uncnt1++;
            o_pos[b[x]].erase(x);
            o_pos[y].insert(x);
            if(pos[b[x]]!=1 and *o_pos[a[pos[b[x]]-1]].begin()>=*o_pos[b[x]].begin()) uncnt2++;
            if(pos[b[x]]!=n and *o_pos[b[x]].begin()>=*o_pos[a[pos[b[x]]+1]].begin()) uncnt2++;
            if(pos[y]!=1 and a[pos[y]-1]!=b[x] and *o_pos[a[pos[y]-1]].begin()>=*o_pos[y].begin()) uncnt2++;
            if(pos[y]!=n and a[pos[y]+1]!=b[x] and *o_pos[y].begin()>=*o_pos[a[pos[y]+1]].begin()) uncnt2++;
            b[x]=y;
            unsucc_cnt+=uncnt2-uncnt1;
            cout<<(unsucc_cnt==0?"YA":"TIDAK")<<'\n';
        }
    }
}
posted @   HaneDaniko  阅读(107)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示