A. Interview with Oleg
这道题主要就是判断ogo,如果前一个ogo与后一个ogo相连(也就是说前一个ogo的最后一个o作为后一个ogo的最前面的o),那么可认为这些ogo是一个部分,用 ∗∗∗ 代替即可。
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 1005
char s[maxn];
bool judge(char a[], int i){
if(a[i] == 'o' && a[i+1] == 'g' && a[i+2] == 'o') return true;
return false;
}
int main(){
int n;
memset(s, '\0', sizeof(s));
scanf("%d %s", &n, s);
int i = 0;
int flag = 0;
vector <char> vec;
while(i < n){
if(judge(s, i)) i += 2, flag = 1;
else{
if(flag) vec.push_back('*'),vec.push_back('*'),vec.push_back('*');
else vec.push_back(s[i]);
i++;
flag = 0;
}
}
for(int i = 0; i < vec.size(); i++)
printf("%c", vec[i]);
printf("\n");
return 0;
}
B. Spotlights
这道题我的想法就是找到一个1然后往4个方向延展即可,计算一下会发现每一个0的位置最多被计算4次,也就是每次的时间复杂度为: O(4∗n∗m) 。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1005;
#define LL long long
int a[maxn][maxn];
int main(){
int n, m;
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
scanf("%d", &a[i][j]);
LL ans = 0;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++){
if(a[i][j] == 1){
for(int k = j-1; k >= 1; k--){
if(a[i][k] == 0) ans++;
else break;
}
for(int k = j+1; k <= m; k++){
if(a[i][k] == 0) ans++;
else break;
}
for(int k = i-1; k >= 1; k--){
if(a[k][j] == 0) ans++;
else break;
}
for(int k = i+1; k <= n; k++){
if(a[k][j] == 0) ans++;
else break;
}
}
}
printf("%I64d\n", ans);
return 0;
}
C. Road to Cinema
c题题目挺长的不过挺容易理解的,我比赛的时候估计脑子抽了,真的太傻了,居然数学公式都没有推出来,其实也就是解个方程而已,服了自己。具体做法就是对每个车的汽油容量进行排序,然后二分查找能满足条件的最小的汽油容量,然后for循环跑一遍找到其中最小的价钱即可。对于二分里面的判断其实我一直都想复杂了,然后后来发现很简单。假设汽车以第一种方式的用油量是x,那么第二种方式的用油量是v-x,那么即可得到x+(v-x)/2 = a[i] (a[i]表示2个相邻汽油站之间的距离),解得x = 2*a[i]-v;于是这段所需要的时间就是3*a[i]-v;
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 2e5+100;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct Node{
LL c, v;
}car[maxn];
int a[maxn];
bool check(int mid, int a[], int len, int t){
LL ans = 0;
for(int i = 1; i <= len; i++){
if(a[i] > mid) return false;
else if(2*a[i] <= mid) ans += a[i];
else ans += 3*a[i] - mid;
}
return ans <= t;
}
int main(){
LL n, k, s, t;
scanf("%I64d%I64d%I64d%I64d", &n, &k, &s, &t);
for(int i = 0; i < n; i++) scanf("%I64d%I64d", &car[i].c, &car[i].v);
for(int i = 1; i <= k; i++) scanf("%d", &a[i]);
a[0] = 0;
a[++k] = s;
sort(a, a+k+1);
for(int i = k; i >= 1; i--) a[i] -= a[i-1];
LL l = 1, r = 1e9+100;
while(l < r){
LL mid = (l+r)/2;
if(check(mid, a, k, t)) r = mid;
else l = mid+1;
}
LL ans = INF;
for(int i = 0; i < n; i++)
if(car[i].v >= r) ans = min(ans, car[i].c);
if(ans < INF) printf("%I64d\n", ans);
else printf("-1");
return 0;
}
D. Sea Battle
一个比较恶心的模拟题,比赛的时候写的有点慢,其实题目给出的n和k可以忽略,没有什么作用,然后就是找每一段连续的0,那么这一段能放的船数最多为 flag/b ,然后模拟处理一下即可。
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+100;
char s[maxn];
int main(){
int n, a, b, k;
scanf("%d%d%d%d", &n, &a, &b, &k);
scanf("%s", s);
int flag = 0, ans = 0;
for(int i = 0; i < n; i++){
if(s[i] == '0') flag++;
else{
if(flag >= b) ans += flag/b;
flag = 0;
}
}
if(flag >= b) ans += flag/b;
printf("%d\n", ans - a + 1);
flag = 0;
ans = ans - a + 1;
for(int i = 0; i < n; i++){
if(s[i] == '0') flag++;
else{
if(flag >= b){
int cnt = flag/b;
int temp = i;
while(cnt > 0 && ans > 0){
temp -= b;
printf("%d ", temp+1);
cnt--;
ans--;
}
if(ans == 0) break;
}
flag = 0;
}
}
if(ans != 0 && flag >= b){
int cnt = flag/b;
int temp = n;
while(cnt > 0 && ans > 0){
temp -= b;
printf("%d ", temp+1);
cnt--;
ans--;
}
}
return 0;
}
E. Subordinates
对于这颗关系树来说我们可以通过枚举树的最大深度来求得答案,对于高为n的关系树,首先我们需要知道这个关系树中有哪里高度是不存在的,假设为cnt,那么对于高于关系树的部分和(高度为0但是不是chief的部分)与cnt相比取最大值即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5+100;
const int INF = 0x3f3f3f3f;
int a[maxn], c[maxn], sum[maxn];
int main(){
int n, s;
scanf("%d%d", &n, &s);
int flag = 0;
memset(a, 0, sizeof(a));
memset(sum, 0, sizeof(sum));
memset(c, 0, sizeof(c));
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
if(i == s){
if(a[i] != 0) flag = 1;
}
else c[a[i]]++;
}
if(n == 1){
if(flag) printf("1\n");
else printf("0\n");
return 0;
}
for(int i = 1; i < n; i++) sum[i] = sum[i-1] + c[i];
int ans = INF, cnt = 0;
for(int i = 1; i < n; i++){
if(!c[i]) cnt++;
ans = min(ans, flag + max(c[0] + sum[n-1] - sum[i], cnt));
}
printf("%d\n", ans);
return 0;
}