Educational Codeforces Round 145 (Rated for Div. 2)
A. Garland
分类讨论
#include <bits/stdc++.h>
using namespace std;
void solve(){
string s;
cin >> s;
map<char,int> cnt;
for( auto c : s ) cnt[c]++;
if( cnt.size() == 1 ){
cout << "-1\n";
}else if( cnt.size() > 2 ){
cout << "4\n";
} else {
int t = cnt.begin()->second;
if( t == 2 ) cout << "4\n";
else cout << "6\n";
}
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int t ; cin >> t;
while( t -- ) solve();
return 0;
}
B. Points on Plane
其实就是在防止的时候间隔一个位置就好。手推一下就能找到规律,注意如果放在距离原点偶数距离的位置上时原点也可以放一个
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read(){
int x = 0 , f = 1 , ch = getchar();
while( (ch < '0' || ch > '9') && ch != '-' ) ch = getchar();
if( ch == '-' ) f = -1 , ch = getchar();
while( ch >= '0' && ch <= '9' ) x = ( x << 3 ) + ( x << 1 ) + ch - '0' , ch = getchar();
return x * f;
}
int32_t main() {
ios::sync_with_stdio(false) , cin.tie(nullptr) , cout.tie(nullptr);
int t , n , l , r , res , mid ;
t = read();
auto f = []( int x ){
if( x & 1 ) return (x+1)*(x+1);
else return x * ( x + 2 ) + 1;
};
while( t -- ){
n = read();
l = 0 , r = 1e9;
while( l <= r ){
mid = ( l + r ) >> 1;
if( f(mid) >= n ) res = mid , r = mid - 1;
else l = mid + 1;
}
cout << res << "\n";
}
return 0;
}
C. Sum on Subarrays
首先找一段长度为\(t\)的区间全部填\(1\),剩余的地方全部都填\(-1000\),即\(1,1,\cdots,1,-1000,-1000\cdots\)
此时,整数区间就是\(\frac{t(t+1)}{2}\),我们求出最大的\(t\)满足\(\frac{t(t+1)}{2}\le k\),此时剩下的所需区间数一定小于\(t\)个
因为
\[\frac{t(t+1)}{2}\le k \le \frac{(t+1)(t+2)}{2}-1\\
0\le k - \frac{t(t+1)}{2}\le \frac{(t+1)(t+2)}{2}-1-\frac{t(t+1)}{2}=t
\]
如果还缺少\(x\)个元素,就把第一个\(-1000\)变成\(k-t-1\),这里的\(k\)是剩下的所需要区间,然后把\(x\)个\(1\)变的大一些(\(500\)就行),满足前\(x\)个元素做左端点,\(k-t-1\)做右端点,恰好有\(x\)个区间是求和是正数。
#include<bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1, ch = getchar();
while ((ch < '0' || ch > '9') && ch != '-') ch = getchar();
if (ch == '-') f = -1, ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x * f;
}
void solve() {
int n = read(), k = read();
vector<int> a(n, -1000);
int l = 0, r = n, mid, t;
while (l <= r) {
mid = (l + r) >> 1;
if (mid * (mid + 1) / 2 <= k) t = mid, l = mid + 1;
else r = mid - 1;
}
k -= t * (t + 1) / 2;
for (int i = 0; i < t; i++) a[i] = 1;
if( k ) a[k-1] = 500 , a[t] = k - t - 1;
for( int i : a ) printf("%d " , i);
printf("\n");
}
int main() {
for (int t = read(); t; t--)
solve();
return 0;
}
D. Binary String Sorting
设状态为\(f[i][0/1/2]\)分别表示前i
位,结尾没有 1、结尾一个 1、结尾多个 1 的最小代价。
很容易想到多次的交换是一定不如删除更优的,因此可以大大的简化转移方程。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e18, c1 = 1e12, c2 = c1 + 1;
// c1 swap , c2 remove
void solve() {
string s;
cin >> s;
int n = s.size();
vector<vector<int>> f(n + 1, vector<int>(3, INF));
f[0][0] = 0;
for (int i = 1; i <= n; i++) {
if (s[i - 1] == '1') {
f[i][0] = f[i - 1][0] + c2;
f[i][1] = f[i - 1][0];
f[i][2] = min(f[i - 1][1], f[i - 1][2]);
} else {
f[i][0] = f[i - 1][0];
f[i][1] = f[i - 1][1] + c1;
f[i][2] = f[i - 1][2] + c2;
}
}
cout << *min_element( f[n].begin() , f[n].end() ) << "\n";
return;
}
int32_t main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
int t;
cin >> t;
for (; t; t--)
solve();
}