Codeforces Round #706 (Div. 2) ABC
A - Split it!
题意
找到 k + 1 k + 1 k+1 个字符串,使得 a 1 + a 2 + ⋯ + a k + a k + 1 + R e v e r s e ( a k ) + ⋯ + R e v e r s e ( a 2 ) + R e v e r s e ( a 1 ) a_1 + a_2 + \dots + a_k + a_{k + 1} + Reverse(a_k) + \dots + Reverse(a_2) + Reverse(a_1) a1+a2+⋯+ak+ak+1+Reverse(ak)+⋯+Reverse(a2)+Reverse(a1) 等于长度为 n n n 的字符串 s s s。
思路
k = 0 k = 0 k=0 肯定可以,其他情况判断是否有 k k k 个字符满足 s i = s n − i ( i ∈ [ 1 , k ] ) s_i = s_{n - i} \ (i \in [1, k]) si=sn−i (i∈[1,k]) ,并且 k ! = n − k k \ != n - k k !=n−k (即除了外面回文这一圈,中间还有剩下的)
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e4 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;
int n, k;
string a;
bool ok()
{
if(k == 0)
return 1;
for(int i = 0, j = n - 1; i < j - 1; i++, j--)
{
if(a[i] != a[j])
return 0;
if(i >= k - 1)
return 1;
}
return 0;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n >> k;
cin >> a;
if(ok())
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}
B - Max and Mex
题意
给定集合 s s s ,每次取其中最大值 x x x 和最小的未出现过的数 y y y ,将 ⌈ a + b 2 ⌉ \lceil \frac{a + b}{2}\rceil ⌈2a+b⌉ 放入集合。问 操作 k k k 次后集合内不重复元素的个数是多少?
思路
首先k=0肯定可以,其他的三种情况,第一种 ⌈ a + b 2 ⌉ > n \lceil \frac{a + b}{2}\rceil \ > \ n ⌈2a+b⌉ > n ,这种情况 k k k 次后增加 k k k 个;其他情况再分为两种,第一种 ⌈ a + b 2 ⌉ \lceil \frac{a + b}{2}\rceil ⌈2a+b⌉ 在原集合中不存在,个数为原集合+1;第二种存在,个数就是原集合个数。
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e5 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;
ll n, k;
map<ll, ll> mp;
set<ll> st;
int solve(int& l, int maxx)
{
int mexx;
for(mexx = l + 1; mexx <= maxx; mexx++)
{
if(!mp[mexx])
break;
}
l = mexx;
int ans = (mexx + maxx + 1) / 2;
return ans;
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n >> k;
mp.clear();
st.clear();
int maxx = -1;
for(int i = 0, x; i < n; i++)
{
cin >> x;
st.insert(x);
mp[x] = 1;
maxx = max(maxx, x);
}
if(k == 0)
{
cout << st.size() << endl;
continue;
}
int mexx = -1;
int nxt = solve(mexx, maxx);
if(mexx > maxx)
{
cout << st.size() + k << endl;
continue;
}
int ans = st.size();
if(st.find(nxt) == st.end())
{
ans++;
}
cout << ans << endl;
}
return 0;
}
C - Diamond Miner
题意
n n n 个矿工都在 y y y 轴上, n n n 个钻石都在 x x x 轴上,每个人挖一个矿,如何使所有人和自己挖的矿的距离之和最小?
思路
把钻石和人都按照和x轴距离排序,然后最近的人挖最近的矿就行。
代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define pb push_back
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e5 + 19;
const int M = 100000;
const ll mod = 1e9 + 7;
const double eps = 1e-12;
int n;
double x, y;
vector<double> goal;
vector<double> miner;
double dis(double x, double y)
{
return sqrt(x * x + y * y);
}
int main()
{
int T;
cin >> T;
while(T--)
{
cin >> n;
miner.clear();
goal.clear();
for(int i = 0, a, b; i < 2 * n; i++)
{
cin >> a >> b;
if(a == 0)
{
b = abs(b);
miner.pb((double)b);
}
else
{
a = abs(a);
goal.pb((double)a);
}
}
sort(miner.begin(), miner.end());
sort(goal.begin(), goal.end());
double ans = 0;
for(int i = 0; i < n; i++)
{
ans += dis(miner[i], goal[i]);
}
printf("%.10f\n", ans);
}
return 0;
}
总结
第一次遇到这么顺利的vp,都是一遍过的,就是很遗憾D题罚坐了一个小时,,,不过这个过题人数确实少,明天补吧
多多包涵,共同进步