A
注意一个人来的时候是要单独做一桌的,和我们平常思维一样。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int qq = 2e5 + 10;
int main(){
int n, a, b; scanf("%d%d%d", &n, &a, &b);
int c = 0;
int x, num = 0;
REP(i, 1, n){
scanf("%d", &x);
if(x == 1){
if(a) a--;
else{
if(b) b--, c++;
else if(c) c--;
else num++;
}
}else{
if(b) b--;
else num += 2;
}
}
printf("%d\n", num);
return 0;
}
B
找到所要构成的最小正方形然后判断即可
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
char st[105][105];
int main(){
int n, m; scanf("%d%d", &n, &m);
int l, r, u, d;
l = d = 1e9;
r = u = -1e9;
int sum = 0;
REP(i, 1, n){
scanf("%s", st[i] + 1);
REP(j, 1, strlen(st[i] + 1)){
if(st[i][j] == 'B'){
l = min(l, i);
r = max(r, i);
u = max(u, j);
d = min(d, j);
sum++;
}
}
}
if(sum == 0){
printf("1\n");
return 0;
}
if(max(r - l, u - d) - min(r - l, u - d) > (r - l > u - d ? m - u + d - 1 : n - r + l - 1)){
puts("-1");
}else{
int p = max(r - l + 1, u - d + 1);
printf("%d\n", p * p - sum);
}
return 0;
}
C
题意:给出n个字串ti,并且这些字串再原串中出现次数为k,给出起始位置,问满足条件的字典序最小的原串
思路:其实归根到底就是维护还未完成填充的位置,之前其实想到了vector,查找是log,但是删除是O(n)的,后来发现并查集也能维护这样的位置
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>
#include <set>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 1e7 + 10;
int fa[qq];
char st[qq];
char ans[qq];
int Find(int x){
return fa[x] == -1 ? x : fa[x] = Find(fa[x]);
}
int main(){
int n, k, LEN = 0, id;
scanf("%d", &n);
mst(fa, -1);
for(int i = 0; i < n; ++i){
scanf("%s", st);
scanf("%d", &k);
int len = strlen(st);
while(k--){
scanf("%d", &id);
for(int j = Find(id); j < id + len; j = fa[j] = Find(j + 1)){
ans[j] = st[j - id];
}
LEN = max(LEN, id + len);
}
}
for(int i = 1; i < LEN; ++i){
if(ans[i] == '\0') ans[i] = 'a';
}
puts(ans + 1);
return 0;
}
D
题意:一棵树中有n个点,k个节点度数为1,其他节点度数大于等于2,并且要求k个节点度数为1的节点之间距离最大的要最小,求出这棵树。
思路:k个度数为1的节点要分成k条链
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i <= n; ++i)
const int MOD = 1e9 + 7;
const int qq = 2e5 + 10;
int vis[qq];
int main(){
int n, k; scanf("%d%d", &n, &k);
int tmp = (n - 1) / k;
int res = tmp * 2;
if((n - 1) % k == 1) res = res + 1;
else if((n - 1) % k >= 2) res = res + 2;
printf("%d\n", res);
for(int i = 2; i <= k + 1; ++i){
printf("1 %d\n", i);
vis[i % k] = i;
}
for(int i = k + 2; i <= n; ++i){
printf("%d %d\n", vis[i % k], i);
vis[i % k] = i;
}
return 0;
}