[lnsyoj1158] 淘淘蓝蓝之幻影树
题意
sol
若某一方胜利,则设该方战胜的区间为 ,那么过程可描述为 打败 , 打败 ………… 打败 。显然, 打败 ………… 打败 , 打败 与之等价,即顺序的正反对结果没有影响。
因此可以将序列翻转进行计算。设 表示从第 个点开始,会被上方的哪一个点击败,特别地,若全部战胜则 。那么每次操作可以将序列倒序并进行处理,若最终结果为 则胜利,否则失败。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 200005, M = N * 2, K = 25;
int h[N], e[M], ne[M], idx;
int vs[K][K];
int n, m, q;
int c[N], f[N][K];
int w[N];
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs_init(int u, int father){
for (int i = 1; i <= m; i ++ )
if (vs[i][c[u]])
f[u][i] = f[father][i];
else
f[u][i] = u;
for (int i = h[u]; ~i; i = ne[i]){
int j = e[i];
if (j == father) continue;
dfs_init(j, u);
}
}
int main(){
// freopen("ex_tree.in", "r", stdin);
memset(h, -1, sizeof h);
scanf("%d%d%d", &n, &m, &q);
for (int i = 1; i <= m; i ++ )
for (int j = 1; j <= m; j ++ )
scanf("%d", &vs[i][j]);
for (int i = 1; i <= n; i ++ ) scanf("%d", &c[i]);
for (int i = 1; i < n; i ++ ){
int x, y;
scanf("%d%d", &x, &y);
add(x, y), add(y, x);
}
dfs_init(1, 0);
while (q -- ){
int k, p;
scanf("%d%d", &k, &p);
for (int i = 1; i <= k; i ++ ) scanf("%d", &w[i]);
for (int i = k; i; i -- ) p = f[p][w[i]];
if (p) puts("0");
else puts("1");
}
}
分类:
题解 / 2025赛时
标签:
DP
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现