Educational Codeforces Round 179 (Rated for Div. 2)
CF2111,简单手速场
A. Energy Crystals
贪心,每次最小值会乘2,直接模拟即可,复杂度 O ( log n ) O(\log n) O(logn)
void solve(){int x;cin>>x;multiset<int> s={0,0,0};int res=0;while(*s.begin()<x){int x=*s.begin();s.erase(s.begin());int y=*s.begin();s.insert(y*2+1);res++;}cout<<res<<"\n";
}
B. Fibonacci Cubes
从这个图可以发现如果 n > 1 n \gt 1 n>1,那么只要能容纳第 n n n个方块和 n − 1 n-1 n−1个方块,由斐波那契数列的性质,必然能容纳全部的方块
void solve(){int n,m;cin>>n>>m;vector<int> fib={0,1,2};for(int i=3;i<=n;i++)fib.push_back(fib[i-1]+fib[i-2]);while(m--){int w,l,h;cin>>w>>l>>h;array<int,3> tmp={w,l,h};ranges::sort(tmp);bool ok=0;if(n==1){if(tmp[2]>=fib[n])ok=1;}else{if(tmp[2]>=fib[n]+fib[n-1]&&tmp[1]>=fib[n]&&tmp[0]>=fib[n])ok=1;}cout<<ok;}cout<<"\n";
}
C. Equal Values
很明显的选取一个连续段,对左右两边操作一次取最小(题意短,好像比ab简单)
void solve(){int n;cin>>n;vector<int> a(n+1);for(int i=1;i<=n;i++)cin>>a[i];int ans=INF;for(int i=1,j;i<=n;i++){j=i;while(j+1<=n&&a[j+1]==a[i])j++;ans=min(ans,(i-1+n-j)*a[i]);i=j;}cout<<ans<<"\n";
}
D. Creating a Schedule
考虑只有两个组的情况,那么只需要两间教室,就可以满足。因此贪心两两配对最大和最小的肯定最优;如果多出一个组,如果还有两间教室,那么这个组单独享用两个教室,否则任意找到之前配对的两个教室和两个组,相互轮换即可(不会改变答案)
void solve(){int n,m;cin>>n>>m;multiset<PII> s;for(int i=1;i<=m;i++){int x;cin>>x;s.insert({x/100,x});}if(n==1){if(s.size()>=2){auto a=*s.begin(),b=*s.rbegin();s.extract(a);s.extract(b);for(int j=1;j<=6;j++){if(j&1)cout<<a.S<<" ";else cout<<b.S<<" ";}}else{auto c=*s.begin();for(int j=1;j<=6;j++)cout<<c.S<<" ";}cout<<"\n";return;}vector<vector<int>> ans(n+1);int nn;if(n&1)nn=n-3;else nn=n;for(int i=1;i<=nn;i+=2){auto a=*s.begin(),b=*s.rbegin();s.extract(a);s.extract(b);int g=0;for(int j=1;j<=6;j++,g^=1){if(!g)ans[i].push_back(a.S),ans[i+1].push_back(b.S);else ans[i].push_back(b.S),ans[i+1].push_back(a.S);}} if(n&1){auto a=*s.begin(),b=*s.rbegin();s.extract(a);s.extract(b);if(s.size()>=2){int g=0;for(int j=1;j<=6;j++,g^=1){if(!g)ans[n-2].push_back(a.S),ans[n-1].push_back(b.S);else ans[n-2].push_back(b.S),ans[n-1].push_back(a.S);}auto a=*s.begin(),b=*s.rbegin();s.extract(a); s.extract(b);g=0;for(int j=1;j<=6;j++,g^=1){if(!g)ans[n].push_back(a.S);else ans[n].push_back(b.S);}}else{auto c=*s.begin();int g=0;for(int j=1;j<=6;j++,g=(g+1)%3){if(g==0)ans[n-2].push_back(a.S),ans[n-1].push_back(c.S),ans[n].push_back(b.S);else if(g==1)ans[n-2].push_back(b.S),ans[n-1].push_back(a.S),ans[n].push_back(c.S);else ans[n-2].push_back(c.S),ans[n-1].push_back(b.S),ans[n].push_back(a.S);}}}for(int i=1;i<=n;i++){for(int j=0;j<6;j++)cout<<ans[i][j]<<" ";cout<<"\n";}
}
signed main(){cin.tie(0)->sync_with_stdio(0);int T=1;cin>>T;while(T--)solve();return 0;
}
E. Changing the String
题意:
- 有只包含
a,b,c
的字符串,q
次操作,给出字符x y
将字符串一个x
替换成y
,或者忽略操作,最后最小化字典序
考虑贪心,从左到右考虑每一位,a则不动,b变成a,c变成a或者b
然后有两种特殊操作,b->c->a
和c->b->a
直接贪会有问题,因为可能c->a
出现在b->c
之前,那么b->c->a
就无法达成
换个思路,我们贪心地配对b->c
和c->a
操作,以及c->b
和b->a
操作,记为bca,cba
·
那么我们有六种操作分别为cb,bc,ca,ba,cba,bca
,其中ca
和ba
前面没有bc,cb
(否则就会合并成bca,cba
),因此这两种操作随便用,贪心用完,剩下的b
和c
没变成a
的我们单独拿出来处理
可以发现这些没变的下标都可以使用bca,cba
变成a
,同时c
可以利用cb
变成b
,因此我们贪心地让b
使用cba
,这样就可以多解放一个cb
操作;让c
使用bca
最后两个都用完了,如果是c
则可以使用cb
变成c
void solve(){ int n,m;cin>>n>>m;string s;cin>>s;int bc,cb,ba,ca,bca,cba;bc=cb=ba=ca=bca=cba=0;for(int i=1;i<=m;i++){char x,y;cin>>x>>y;if(x=='b'&&y=='a'){if(cb>0){cb--;cba++;}else ba++;}else if(x=='c'&&y=='a'){if(bc>0){bc--;bca++;}else ca++;}else if(x=='b'&&y=='c')bc++;else if(x=='c'&&y=='b')cb++;}vector<int> tmp;for(int i=0;i<n;i++){if(s[i]=='a')continue;if(s[i]=='b'){if(ba>0){ba--;s[i]='a';continue;}tmp.push_back(i);continue;}if(s[i]=='c'){if(ca>0){ca--;s[i]='a';continue;}tmp.push_back(i);continue; }}for(auto x:tmp){if(bca&&cba){if(s[x]=='b'){cba--;cb++;s[x]='a';}else{bca--;bc++;s[x]='a';}}else if(bca){bca--;if(s[x]=='c')bc++;s[x]='a';}else if(cba){cba--;if(s[x]=='b')cb++;s[x]='a';}else{if(s[x]=='c'&&cb){cb--;s[x]='b';}}}cout<<s<<"\n";
}
F. Puzzle
枚举周长,发现周长只和最大最小坐标有关,因此我们可以先使用一个L
字形固定住周长,然后看面积是否合法,贪心地往里面放格子填满即可
可以证明这是正确的,因为两条边的和确定了,假设为 P P P,那么面积的最值,由均值不等式可得,最大值就是 P + 1 2 ∗ P 2 \frac{P+1}{2}*\frac{P}{2} 2P+1∗2P,最小值就是 ( P − 1 ) ∗ 1 (P-1)*1 (P−1)∗1
void solve(){ int p,s;cin>>p>>s;for(int P=2;P<=50001;P++){if(2*P*s%p!=0)continue;int S=2*P*s/p;if(S>(P>>1)*(P+1>>1)||S<P-1)continue;int w=P>>1,h=P+1>>1;cout<<S<<"\n";for(int i=0;i<w;i++)cout<<i<<" 0\n";for(int i=1;i<h;i++)cout<<"0 "<<i<<"\n";int need=S-(w+h-1);for(int i=1;i<w&&need;i++){for(int j=1;j<h&&need;j++){cout<<i<<" "<<j<<"\n";need--;}}return;}cout<<"-1\n";
}