【学习笔记】CF1510J Japanese Game

写这篇题解单纯是因为考场上把这道题想错了,其实也没啥特别难的地方。

方便起见,下文用 01 01 01串来叙述。考虑假设没有被固定的 0 0 0的数目为 K K K,那么我们可以先把这 K K K 0 0 0放到最前面,这样每一个连续的 1 1 1可以表述为区间 [ l i , r i ] [l_i,r_i] [li,ri]。那么将这 K K K 0 0 0挪到最后面过后就变成了 [ l i , r i − K + 1 ] [l_i,r_i-K+1] [li,riK+1],如果长度不足 K K K就全部变成 0 0 0

想明白这个过程过后,这道题就非常简单了。注意到 K ∈ [ 0 , 3 ] K\in [0,3] K[0,3](因为实现一段连续的 0 0 0是容易的,只要 01 01 01交错就行,所以 K K K很大是不必要的),因此可以直接暴力枚举 K K K然后判断。

复杂度 O ( n ) O(n) O(n)

难得写了注释

#include<bits/stdc++.h> #define fi first #define se second #define pb push_back using namespace std; int n; string s; vector<int>vec; vector<pair<int,int>>seq; void check2(){ int tot=0; for(int i=0;i<n;i++)tot+=(s[i]=='_'); if(tot==n){ cout<<0; exit(0); } if(s[0]=='_'||s[n-1]=='_')return; for(int i=1;i<n;i++){ if(s[i]=='_'&&s[i-1]=='_')return; } for(auto x:seq){ vec.pb(x.se-x.fi+1); } cout<<vec.size()<<"\n"; for(auto x:vec){ cout<<x<<"\n"; } exit(0); } int check(int Mid){ for(int i=0;i<Mid;i++){ if(s[i]=='#'){ return 0; } } vec.clear(); //处理第一段的情况 int tot=0; for(int i=0;i<n;i++){ if(s[i]=='_'){ tot++; } else{ break; } } tot-=Mid; if(tot==1)return 0; if(tot>1&&tot%2==0){ for(int i=1;i<=tot/2;i++)vec.pb(1); } if(tot>1&&tot%2==1){ if(Mid==1)return 0; vec.pb(2); for(int i=1;i<=tot/2-1;i++)vec.pb(1); } //处理中间段的情况 for(int i=1;i<seq.size();i++){ int Len=seq[i].fi-seq[i-1].se-1; if(Len<=Mid){ return 0; } vec.pb(seq[i-1].se-seq[i-1].fi+1+Mid); Len-=Mid; if(Len%2==1){ for(int j=1;j<=Len/2;j++)vec.pb(1); } else if(Len>2&&Mid>=2){ vec.pb(2); for(int j=1;j<=(Len-1)/2-1;j++)vec.pb(1); } else return 0; } //处理最后一段的情况 tot=0; for(int i=n-1;i>=0;i--){ if(s[i]=='_'){ tot++; } else{ break; } } if(tot<Mid){ return 0; } vec.pb(seq.back().se-seq.back().fi+1+Mid); tot-=Mid; if(tot==1)return 0; if(tot>1&&tot%2==0){ for(int i=1;i<=tot/2;i++)vec.pb(1); } if(tot>1&&tot%2==1){ if(Mid==1)return 0; vec.pb(2); for(int i=1;i<=tot/2-1;i++)vec.pb(1); } return 1; } int main(){ ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>s,n=s.size(); for(int i=0;i<n;i++){ if(s[i]=='#'){ int j=i;while(j+1<n&&s[j+1]=='#')j++; seq.pb({i,j}),i=j; } } check2(); // 判断不移动的情况,或者全为0的情况 for(int i=1;i<=3;i++){ //fixed if(check(i)){ cout<<vec.size()<<"\n"; for(auto x:vec)cout<<x<<" "; return 0; } } cout<<-1; }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530008.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(14)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
历史上的今天:
2022-03-28 【题解】[NOI Online 2022 提高组] 如何正确地排序
点击右上角即可分享
微信分享提示