THUPC2022初赛
J. THUPC


先按照行列坐标排序,并合并相交的线段
之后只有 \(15\) 条线段,并且一个字符的拼接方式唯一,直接 dfs 即可
// input
17
1 0 5 2
0 0 3 5
0 3 4 5
1 2 7 7
1 2 7 10
0 7 10 4
0 11 13 1
1 1 7 11
1 1 7 13
1 0 6 15
0 15 16 5
0 15 16 6
1 5 6 16
1 3 6 18
1 4 7 18
0 18 21 3
0 18 21 7
// output
Yes
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
struct LineUp {
int d, u, x;
int id;
};
bool operator < (LineUp l1, LineUp l2) {
return l1.x != l2.x ? l1.x < l2.x :
l1.d != l2.d ? l1.d < l2.d :
l1.u > l2.u;
}
struct LineLeft {
int l, r, y;
int id;
};
bool operator < (LineLeft l1, LineLeft l2) {
return l1.y != l2.y ? l1.y < l2.y :
l1.l != l2.l ? l1.l < l2.l :
l1.r > l2.r;
}
vector<LineUp> lu;
vector<LineLeft> ll;
int cnt;
int n;
int fa[N];
int getfa(int x) {
return x == fa[x] ? x : fa[x] = getfa(fa[x]);
}
char str[N] = "THUPC";
int vislu[N], visll[N];
#define make_LL(n) int l##n = L##n.l, r##n = L##n.r, y##n = L##n.y
#define make_LU(n) int d##n = L##n.d, u##n = L##n.u, x##n = L##n.x
int check_T(LineLeft L1, LineUp L2) {
make_LL(1);
make_LU(2);
return getfa(L1.id) == getfa(L2.id)
&& d2 < y1 && y1 == u2 && l1 < x2 && x2 < r1;
}
int check_H(LineUp L3, LineLeft L4, LineUp L5) {
make_LU(3);
make_LL(4);
make_LU(5);
return getfa(L3.id) == getfa(L4.id) && getfa(L4.id) == getfa(L5.id)
&& d3 == d5 && d5 < y4 && y4 < u3 && u3 == u5 && x3 == l4 && l4 < r4 && r4 == x5;
}
int check_U(LineUp L6, LineLeft L7, LineUp L8) {
make_LU(6);
make_LL(7);
make_LU(8);
return getfa(L6.id) == getfa(L7.id) && getfa(L7.id) == getfa(L8.id)
&& d6==d8 && d8==y7 && y7<u6 && u6==u8 && x6==l7 && l7<r7 && r7==x8;
}
int check_P(LineUp L9, LineLeft L10, LineLeft L11, LineUp L12) {
make_LU(9);
make_LL(10);
make_LL(11);
make_LU(12);
return getfa(L9.id) == getfa(L10.id) && getfa(L10.id) == getfa(L11.id) && getfa(L11.id) == getfa(L12.id)
&& d9<y11 && y11==d12 && d12<u9 && u9==y10 && y10==u12 && x9==l10 && l10==l11 && l11<r10 && r10==r11 && r11==x12;
}
int check_C(LineUp L13, LineLeft L14, LineLeft L15) {
make_LU(13);
make_LL(14);
make_LL(15);
return getfa(L13.id) == getfa(L14.id) && getfa(L14.id) == getfa(L15.id)
&& d13==y15 && y15<u13 && u13==y14 && x13==l14 && l14==l15 && l15<r14 && r14==r15;
}
void dfs(int stp) {
if(stp == 5) {
puts("Yes");
exit(0);
}
// putchar(str[stp]);
if(str[stp] == 'T') {
for(int i = 0 ; i < ll.size() ; ++ i) {
if(!visll[i]) {
visll[i] = 1;
for(int j = 0 ; j < lu.size() ; ++ j) {
if(!vislu[j]) {
vislu[j] = 1;
if(check_T(ll[i], lu[j])) {
dfs(stp + 1);
puts("No"); exit(0);
}
vislu[j] = 0;
}
}
visll[i] = 0;
}
}
} else if(str[stp] == 'H') {
for(int i = 0 ; i < lu.size() ; ++ i) {
if(!vislu[i]) {
vislu[i] = 1;
for(int j = 0 ; j < ll.size() ; ++ j) {
if(!visll[j]) {
visll[j] = 1;
for(int k = 0 ; k < lu.size() ; ++ k) {
if(!vislu[k]) {
vislu[k] = 1;
if(check_H(lu[i], ll[j], lu[k])) {
dfs(stp + 1);
puts("No"); exit(0);
}
vislu[k] = 0;
}
}
visll[j] = 0;
}
}
vislu[i] = 0;
}
}
} else if(str[stp] == 'U') {
for(int i = 0 ; i < lu.size() ; ++ i) {
if(!vislu[i]) {
vislu[i] = 1;
for(int j = 0 ; j < ll.size() ; ++ j) {
if(!visll[j]) {
visll[j] = 1;
for(int k = 0 ; k < lu.size() ; ++ k) {
if(!vislu[k]) {
vislu[k] = 1;
if(check_U(lu[i], ll[j], lu[k])) {
dfs(stp + 1);
puts("No"); exit(0);
}
vislu[k] = 0;
}
}
visll[j] = 0;
}
}
vislu[i] = 0;
}
}
} else if(str[stp] == 'P') {
for(int i = 0 ; i < lu.size() ; ++ i) {
if(!vislu[i]) {
vislu[i] = 1;
for(int j = 0 ; j < ll.size() ; ++ j) {
if(!visll[j]) {
visll[j] = 1;
for(int k = 0 ; k < ll.size() ; ++ k) {
if(!visll[k]) {
visll[k] = 1;
for(int w = 0 ; w < lu.size() ; ++ w) {
if(!vislu[w]) {
vislu[w] = 1;
if(check_P(lu[i], ll[j], ll[k], lu[w])) {
dfs(stp + 1);
puts("No"); exit(0);
}
vislu[w] = 0;
}
}
visll[k] = 0;
}
}
visll[j] = 0;
}
}
vislu[i] = 0;
}
}
} else if(str[stp] == 'C') {
for(int i = 0 ; i < lu.size() ; ++ i) {
if(!vislu[i]) {
vislu[i] = 1;
for(int j = 0 ; j < ll.size() ; ++ j) {
if(!visll[j]) {
visll[j] = 1;
for(int k = 0 ; k < ll.size() ; ++ k) {
if(!visll[k]) {
visll[k] = 1;
if(check_C(lu[i], ll[j], ll[k])) {
dfs(stp + 1);
puts("No"); exit(0);
}
visll[k] = 0;
}
}
visll[j] = 0;
}
}
vislu[i] = 0;
}
}
}
puts("No"); exit(0);
}
int fafatmp[N];
int main() {
scanf("%d", &n);
for(int i = 1 ; i <= n ; ++ i) {
int op; scanf("%d", &op);
if(op == 0) {
int l, r, y;
scanf("%d%d%d", &l, &r, &y);
ll.emplace_back((LineLeft) { l, r, y, 0 });
} else {
int d, u, x;
scanf("%d%d%d", &d, &u, &x);
lu.emplace_back((LineUp) { d, u, x, 0 });
}
}
sort(ll.begin(), ll.end());
sort(lu.begin(), lu.end());
cnt = 0;
if(ll.size()) {
vector<LineLeft> tmp;
for(int i = 0 ; i < ll.size() ; ) {
if(i == 0 || ll[i - 1].y != ll[i].y) {
int j = i, y = ll[i].y;
while(j + 1 < ll.size() && ll[j + 1].y == ll[i].y) ++ j;
int L = ll[i].l, R = ll[i].r;
for(int k = i ; k <= j ; ++ k) {
if(ll[k].l <= R) {
R = max(R, ll[k].r);
} else {
tmp.emplace_back((LineLeft) {L, R, y, ++ cnt});
L = ll[k].l, R = ll[k].r;
}
}
tmp.emplace_back((LineLeft) {L, R, y, ++ cnt});
i = j + 1;
} else break;
}
ll = tmp;
}
if(lu.size()) {
vector<LineUp> tmp;
for(int i = 0 ; i < lu.size() ; ) {
if(i == 0 || lu[i - 1].x != lu[i].x) {
int j = i, x = lu[i].x;
while(j + 1 < lu.size() && lu[j + 1].x == lu[i].x) ++ j;
int D = lu[i].d, U = lu[i].u;
for(int k = i ; k <= j ; ++ k) {
if(lu[k].d <= U) {
U = max(U, lu[k].u);
} else {
tmp.emplace_back((LineUp) {D, U, x, ++ cnt});
D = lu[k].d, U = lu[k].u;
}
}
tmp.emplace_back((LineUp) {D, U, x, ++ cnt});
i = j + 1;
} else break;
}
lu = tmp;
}
// cout << lu.size() << ' ' << ll.size() << endl;
if(lu.size() != 8 || ll.size() != 7) {
puts("No");
} else {
for(int i = 1 ; i <= cnt ; ++ i) fa[i] = i;
for(int i = 0 ; i < lu.size() ; ++ i) {
for(int j = 0 ; j < ll.size() ; ++ j) {
if(lu[i].d <= ll[j].y && ll[j].y <= lu[i].u
&& ll[j].l <= lu[i].x && lu[i].x <= ll[j].r) {
fa[getfa(lu[i].id)] = getfa(ll[j].id);
}
}
}
int tot = 0;
for(int i = 1 ; i <= cnt ; ++ i) {
if(getfa(i) == i) {
++ tot;
}
}
if(tot == 5) {
dfs(0);
} else {
puts("No");
}
}
// printf("ll size = %d, lu size = %d\n", ll.size(), lu.size());
}
K. 数正方体



// input
14 17
....+---+---+....
.../ / /|....
..+---+---+ |....
./ /| | +---+
+---+ | |/ /|
| | +---+---+ |
| |/ /| | +
+---+---+ | |/|
| | | +---+ |
| | |/ /| +
+---+---+---+ |/.
| | | | +..
| | | |/...
+---+---+---+....
// output
14

头顶标数法即可,但从上往下不太好搞,不妨从前往后 dfs,相邻两层通过 / 连接,如果一个位置是 +,并且它的左下角是空格,那么统计这个位置为一个面
#include <bits/stdc++.h>
using namespace std;
const int N = 1100;
int n, m;
char s[N][N];
int vis[N][N];
struct P {
int x, y;
};
queue<P> que;
int cnt;
int pak[N];
void dfs(int x, int y) {
if(vis[x][y] || !(1 <= x && x <= n && 1 <= y && y <= m)) return ;
vis[x][y] = 1;
if(s[x][y] == '+') {
if(s[x][y - 1] == '-' && s[x + 1][y] == '|' && s[x + 1][y - 1] == ' ') {
pak[cnt] ++;
}
}
int mv[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for(int i = 0 ; i < 4 ; ++ i) {
int nx = x + mv[i][0], ny = y + mv[i][1];
if(s[nx][ny] == '-' || s[nx][ny] == '|' || s[nx][ny] == '+') {
dfs(nx, ny);
}
}
if(s[x - 1][y + 1] == '/') {
que.push((P) {x - 2, y + 2});
}
}
int getfkc(char *s) {
char c = getchar();
while(c == '\n' || c == '\r') c = getchar();
int t = 0;
while(c != '\n' && c != '\r') {
s[t ++] = c;
c = getchar();
}
return t;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1 ; i <= n ; ++ i) {
while(!getfkc(s[i] + 1));
}
que.push((P) {n, 1});
while(que.size()) {
P fro = que.front(); que.pop();
while(vis[fro.x][fro.y] && que.size()) {
fro = que.front(); que.pop();
}
if(vis[fro.x][fro.y]) break;
++ cnt;
dfs(fro.x, fro.y);
}
int ans = 0;
for(int i = 1 ; i <= cnt ; ++ i) {
ans += pak[i] * (cnt - i);
}
printf("%d\n", ans);
}

浙公网安备 33010602011771号