长安大学第四届ACM-ICPC“迎新杯”程序设计竞赛-重现赛 G - 彩虹岛套娃
题目描述
俄罗斯套娃是俄罗斯特产的木制玩具,一般由多个一样图案的空心木娃娃一个套一个组成,最多可达十多个,通常为圆柱形,底部平坦可以直立。颜色有红色,蓝色,绿色,紫色等。最普通的图案是一个穿着俄罗斯民族服装的姑娘,叫做“玛特罗什卡”,这也成为这种娃娃的通称。
1. 空心木娃娃只有正方体与球两种形状。
2. 正方体娃娃与球体娃娃可以相互套,也可以相同形状之间套。
3. 当两形状相切的时候使能够互相嵌套的,比如半径为2的球体能套在边长为4的正方体中。
4. 所有木娃娃的厚度可以忽略不计。
现在有𝑛个正方体和𝑚个球形的木娃娃,其中第𝑖个正方体娃娃边长为𝑎𝑖,第𝑗个球形娃娃半径为𝑟𝑗。用这些娃娃组成一个套娃,最多有几层?
数据保证所有正方体边长不相同,所有的圆半径不相同。
输入描述:
输入第一行为一个整数𝑇(1 ≤ 𝑇 ≤ 25),表示一共有𝑇组测试数据。
对于每组测试数据:
第一行有两个整数𝑛,𝑚(1 ≤ 𝑛,𝑚 ≤ 105),分别表示正方体和球体的木娃娃数。
第二行有𝑛个整数,其中第𝑖个整数𝑎𝑖(1 ≤ 𝑎𝑖 ≤ 109)代表第𝑖个正方体娃娃的边长。
第二行有𝑚个整数,其中第𝑖个整数𝑟𝑖(1 ≤ 𝑟𝑖 ≤ 109)代表第𝑖个球形娃娃的半径。
输出描述:
输出一个正整数𝑥,表示组成的套娃的层数。
示例1
输入
1 3 4 2 4 6 7 5 3 1
输出
5
说明
对于样例,套娃分别由半径为7的球形、半径为5的球形、边长为4的正方体、边长为2的正方体、半径为1 的球形的木娃娃组成,一共5层。
题解
$dp$。
可以构造出一个$DAG$,然后看最长路的长度就可以了。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 8e5 + 10;
int T;
int n, m;
long long a[maxn], b[maxn];
int dp[maxn];
int h[maxn];
int to[maxn];
int nx[maxn];
int sz;
int in[maxn];
void add(int x, int y) {
// cout << x << " -> " << y <<endl;
to[sz] = y;
nx[sz] = h[x];
h[x] = sz;
sz ++;
}
int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &m);
int ans = 0;
sz = 0;
for(int i = 1; i <= n + m; i ++) {
h[i] = -1;
in[i] = 0;
dp[i] = 0;
}
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
if(i < n) {
add(i, i + 1);
in[i + 1] ++;
}
}
for(int i = 1; i <= m; i ++) {
scanf("%lld", &b[i]);
if(i < m) {
add(i + n, i + 1 + n);
in[i + 1 + n] ++;
}
}
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + m);
for(int i = 1; i <= n; i ++) {
int L = 1, R = m, pos = -1;
while(L <= R) {
int mid = (L + R) / 2;
if(2LL * b[mid] <= a[i]) {
L = mid + 1;
pos = mid;
} else {
R = mid - 1;
}
}
if(pos != -1) {
add(pos + n, i);
in[i] ++;
}
}
for(int i = 1; i <= m; i ++) {
int L = 1, R = n, pos = -1;
while(L <= R) {
int mid = (L + R) / 2;
if(3LL * a[mid] * a[mid] <= 4LL * b[i] * b[i]) {
L = mid + 1;
pos = mid;
} else {
R = mid - 1;
}
}
if(pos != -1) {
add(pos, i + n);
in[i + n] ++;
}
}
queue<int> Q;
for(int i = 1; i <= n + m; i ++) {
if(in[i] == 0) {
Q.push(i);
dp[i] = 1;
}
}
while(!Q.empty()) {
int node = Q.front();
Q.pop();
ans = max(ans, dp[node]);
for(int i = h[node]; i != -1; i = nx[i]) {
dp[to[i]] = max(dp[to[i]], dp[node] + 1);
in[to[i]] --;
if(in[to[i]] == 0) {
Q.push(to[i]);
}
}
}
printf("%d\n", ans);
}
return 0;
}

浙公网安备 33010602011771号