[BZOJ4154][Ipsc2015]Generating Synergy
[BZOJ4154][Ipsc2015]Generating Synergy
试题描述
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色
输入
第一行一个数T,表示数据组数
接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数
接下来一行n-1个数描述2..n的父节点
接下来q行每行三个数a,l,c
若c为0,表示询问a的颜色
否则将距离a不超过l的a的子节点染成c
输出
设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+...+z_q模10^9+7
输入示例
1 4 3 7 1 2 2 3 0 0 2 1 3 3 0 0 1 0 2 2 0 0 4 1 1 4 0 0
输出示例
32
数据规模及约定
对于100%的数据T<=6,n,m,c<=10^5,
1<=a<=n,0<=l<=n,0<=c<=c
题解
一开始看错题了。。。后来才发现只染子树中的点。
那么就可以以每个节点的 DFS 序作为横坐标,深度作为纵坐标,那么就可以把一棵树放在坐标系里了,一次 a 节点,距离为 l 的染色就是纵坐标从 dep[a] 到 dep[a] + l,横坐标从 dfsx[a] 到 dfsx[a] + siz[a] - 1 的矩形,其中 dep[a] 表示节点 a 的深度,dfsx[a] 指节点 a 的 DFS 序,siz[a] 表示以节点 a 为根的子树大小。需要标记下传。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; const int BufferSize = 1 << 16; char buffer[BufferSize], *Head, *Tail; inline char Getchar() { if (Head == Tail) { int l = fread(buffer, 1, BufferSize, stdin); Tail = (Head = buffer) + l; } return *Head++; } int read() { int x = 0, f = 1; char c = Getchar(); while (!isdigit(c)){ if (c == '-' ) f = -1; c = Getchar(); } while (isdigit(c)){ x = x * 10 + c - '0' ; c = Getchar(); } return x * f; } #define maxn 100010 #define maxm 200010 #define oo 2147483647 #define MOD 1000000007 #define LL long long int n, m, fa[maxn], dep[maxn], head[maxn], next[maxm], to[maxm], dl[maxn], dr[maxn]; void AddEdge( int a, int b) { to[++m] = b; next[m] = head[a]; head[a] = m; swap(a, b); to[++m] = b; next[m] = head[a]; head[a] = m; return ; } int clo; void build( int u, int d) { dl[u] = ++clo; dep[u] = d; for ( int e = head[u]; e; e = next[e]) if (to[e] != fa[u]) build(to[e], d + 1); dr[u] = clo; return ; } int root, lc[maxn], rc[maxn]; bool Cur; struct Node { int x[2], mx[2], mn[2], col, setv; bool operator < ( const Node& t) const { return x[Cur] < t.x[Cur]; } bool operator == ( const Node& t) const { return x[0] == t.x[0] && x[1] == t.x[1]; } } ns[maxn]; void maintain( int o) { int l = lc[o], r = rc[o]; for ( int i = 0; i < 2; i++) { ns[o].mx[i] = max(max(ns[l].mx[i], ns[r].mx[i]), ns[o].x[i]); ns[o].mn[i] = min(min(ns[l].mn[i], ns[r].mn[i]), ns[o].x[i]); } return ; } void build( int & o, int L, int R, bool cur) { if (L > R){ o = 0; return ; } int M = L + R >> 1; o = M; Cur = cur; nth_element(ns + L, ns + M, ns + R + 1); build(lc[o], L, M - 1, cur ^ 1); build(rc[o], M + 1, R, cur ^ 1); maintain(o); return ; } Node x, y; void pushdown( int o) { if (!ns[o].setv) return ; ns[o].col = ns[lc[o]].setv = ns[rc[o]].setv = ns[o].setv; ns[o].setv = 0; return ; } bool all( int o) { return x.x[0] <= ns[o].mn[0] && ns[o].mx[0] <= y.x[0] && x.x[1] <= ns[o].mn[1] && ns[o].mx[1] <= y.x[1]; } bool has( int o) { return !(ns[o].mx[0] < x.x[0] || ns[o].mn[0] > y.x[0] || ns[o].mx[1] < x.x[1] || ns[o].mn[1] > y.x[1]); } void update( int o, int c) { if (!o) return ; pushdown(o); int xx = ns[o].x[0], yy = ns[o].x[1]; if (x.x[0] <= xx && xx <= y.x[0] && x.x[1] <= yy && yy <= y.x[1]) ns[o].col = c; if (all(lc[o])) ns[lc[o]].setv = c; else if (has(lc[o])) update(lc[o], c); if (all(rc[o])) ns[rc[o]].setv = c; else if (has(rc[o])) update(rc[o], c); return ; } int query( int o) { if (!o) return -1; pushdown(o); if (x == ns[o]) return ns[o].col; int tmp = -1; if (ns[lc[o]].mn[0] <= x.x[0] && x.x[0] <= ns[lc[o]].mx[0] && ns[lc[o]].mn[1] <= x.x[1] && x.x[1] <= ns[lc[o]].mx[1]) tmp = query(lc[o]); if (tmp < 0) tmp = query(rc[o]); return tmp; } int main() { ns[0].mx[0] = ns[0].mx[1] = -oo; ns[0].mn[0] = ns[0].mn[1] = oo; int T = read(); while (T--) { m = 0; memset(head, 0, sizeof (head)); n = read(); int c = read(), q = read(); for ( int i = 2; i <= n; i++) AddEdge(fa[i] = read(), i); clo = 0; build(1, 1); for ( int i = 1; i <= n; i++) ns[i].x[0] = dl[i], ns[i].x[1] = dep[i], ns[i].col = 1, ns[i].setv = 0; build(root, 1, n, 0); LL ans = 0; for ( int i = 1; i <= q; i++) { int a = read(), l = read(), c = read(), tmp = 0; if (c) { x.x[0] = dl[a]; y.x[0] = dr[a]; x.x[1] = dep[a]; y.x[1] = dep[a] + l; update(root, c); } else { x.x[0] = dl[a]; x.x[1] = dep[a]; tmp = query(root); } ans += (LL)tmp * i; if (ans >= MOD) ans %= MOD; } printf( "%lld\n" , ans); } return 0; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App