题意

click here

题解

我们首先考虑答案是个什么样的东西, 不难 发现每个点可以单独计算它的贡献。

令每个点 \(i\) 崛起次数为 \(a_i\) 。

假设一个点子树的 \(\sum a_i\) 分别为 \(b_1,b_2,\dots,b_k\) ,令 \(S = a_i + \sum b_j\) 。

那么这个点的答案为

\[\min (2(S - \max(\max\{b_j\}, a_i)), S - 1)
\]

至于为什么是这样可以简单说明下:

\(S - 1\) :显然是这个点的答案的上界,除了第一次,后面每一次最多对这个点贡献一次。

\(2(S - \max(\max\{b_j\}, a_i))\) :不难发现,我们总可以找到一种方案使得 \(S - \max\) 那种与 剩下的 \(\max(\max\{b_j\}, a_i)\) 交错出现,使得这个答案取得上界,然后每次会存在两种贡献。

这样我们就可以得到一个 \(O(n)\) 的 \(dp\) 了。


我们考虑如何动态维护这个 \(dp\) 。

不难发现这个操作及其类似于 Link_Cut_Tree 中的 Access 操作。

我们令 \(b_u = \sum_{v \in child(u)} a_v\) 也就是 \(u\) 的子树 \(a\) 和。

我们考虑维护这个东西,不难发现每次给一个点的 \(a_u\) 加上 \(v\) ,相当于把这个点到根的 \(b_u\) 加上 \(v\) 。

然后考虑如何维护一个点的贡献,如果 \(u\) 存在一个儿子 \(v\) 使得 \(b_v \times 2 > b_u + 1\) 那么我们定义 \(v \to u\) 为实边。

其余的边都为虚边。不难发现这些实边会对于 \(u\) 存在 \(2(b_u - b_v)\) 的贡献。( \(a\) 不可能存在贡献,因为 \(b_v\) 已经占据一半了)

然后虚边的贡献就是 \(\min(b_u - 1, 2(b_u - a_u))\) 。

这个可以自己列列不等式,讨论讨论就行了。

然后我们每次 Access 操作就是将链上的一些点加权,并且更换虚实边就行了,重新计算贡献就行了。

这个直接用支持加法标记的 LCT 维护就行了。

不难发现一个点到根的实边最多是 \(\log w\) 条,因为每条实边会使得权值至少翻倍。

所以最后复杂度就是 \(O(n + q\log w)\) 的。

总结

有些题,我们先找出它的一些巧妙性质以及结论,然后考虑用数据结构维护。(这似乎也是出题的好思路?)

代码

不太会写的话还是建议看看代码的。。

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__) using namespace std; typedef long long ll;
inline bool chkmin(ll &a, ll b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(ll &a, ll b) {return b > a ? a = b, 1 : 0;} inline int read() {
int x = 0, fh = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') fh = -1;
for (; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
return x * fh;
} void File() {
#ifdef zjp_shadow
freopen ("374.in", "r", stdin);
freopen ("374.out", "w", stdout);
#endif
} const int N = 4e5 + 1e3; int n, m;
vector<int> G[N]; int son[N]; ll Ans, ans[N], b[N], a[N];
inline void ReCalc(int u) {
Ans -= ans[u];
ans[u] = son[u] ? 2 * (b[u] - b[son[u]]) : b[u] - 1;
if (a[u] * 2 > b[u] + 1) ans[u] = 2 * (b[u] - a[u]);
Ans += ans[u];
} #define ls(o) ch[o][0]
#define rs(o) ch[o][1] namespace Link_Cut_Tree { int ch[N][2], fa[N]; inline bool get(int o) { return o == rs(fa[o]); } inline bool is_root(int o) { return o != ls(fa[o]) && o != rs(fa[o]); } inline void Rotate(int v) {
int u = fa[v], t = fa[u], d = get(v);
fa[ch[u][d] = ch[v][d ^ 1]] = u;
fa[v] = t; if (!is_root(u)) ch[t][rs(t) == u] = v;
fa[ch[v][d ^ 1] = u] = v;
} ll tag[N];
inline void Add(int o, ll uv) { if (o) b[o] += uv, tag[o] += uv; } inline void Push_Down(int o) {
if (!tag[o]) return ;
Add(ls(o), tag[o]);
Add(rs(o), tag[o]); tag[o] = 0;
} inline void Push_All(int o) {
if (!is_root(o)) Push_All(fa[o]); Push_Down(o);
} inline void Splay(int o) {
Push_All(o);
for (; !is_root(o); Rotate(o))
if (!is_root(fa[o])) Rotate(get(o) != get(fa[o]) ? o : fa[o]);
} inline int Get_Root(int o) {
while (ls(o)) Push_Down(o), o = ls(o); return o;
} inline void Access(int o, int uv) {
for (int t = 0; o; o = fa[t = o]) {
Splay(o);
b[o] += uv; Add(ls(o), uv); if (son[o]) {
Push_All(son[o]);
if (b[son[o]] * 2 <= b[o] + 1) son[o] = rs(o) = 0;
}
int to = Get_Root(t);
if (b[to] * 2 > b[o] + 1) son[o] = to, rs(o) = t;
ReCalc(o);
}
} } void Dfs_Init(int u, int fa = 0) {
Link_Cut_Tree :: fa[u] = fa; b[u] = a[u]; int to = 0;
for (int v : G[u]) if (v != fa) {
Dfs_Init(v, u); b[u] += b[v];
if (b[v] > b[to]) to = v;
}
if (b[to] * 2 > b[u]) son[u] = Link_Cut_Tree :: rs(u) = to; ReCalc(u);
} int main () { File(); n = read(); m = read();
For (i, 1, n) a[i] = read();
For (i, 1, n - 1) {
int u = read(), v = read();
G[u].push_back(v); G[v].push_back(u);
}
Ans = 0; Dfs_Init(1); printf ("%lld\n", Ans);
For (i, 1, m) {
int pos = read(), val = read();
a[pos] += val; Link_Cut_Tree :: Access(pos, val);
printf ("%lld\n", Ans);
} return 0;
}

LOJ #2434. 「ZJOI2018」历史(LCT)的更多相关文章

  1. @loj - 2434@ 「ZJOI2018」历史

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的 ...

  2. LOJ2434. 「ZJOI2018」历史 [LCT]

    LOJ 思路 第一眼看似乎没有什么思路,试着套个DP上去:设\(dp_x\)表示只考虑\(x\)子树,能得到的最大答案. 合并的时候发现只有\(x\)这个点有可能做出新的贡献,而做出新贡献的时候必然是 ...

  3. 「ZJOI2018」历史(LCT)

    「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...

  4. 「ZJOI2018」历史

    「ZJOI2018」历史 前置知识 \(\text{LCT}\) 维护子树信息,考虑辅助树上一个节点的子树信息只是其代表的这一段链的信息,设 \(S(u)\) 为节点 \(u\) 的子树信息,那么在辅 ...

  5. Loj #2529. 「ZJOI2018」胖

    Loj #2529. 「ZJOI2018」胖 题目描述 Cedyks 是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公. Cedyks 是一个富有的男孩子.他住在著名的 The P ...

  6. 题解 「ZJOI2018」历史

    题目传送门 Description 九条可怜是一个热爱阅读的女孩子. 这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣. 这个世界有 \(n\) 个城市,这 \(n\) 个城市被恰 ...

  7. LOJ#2230. 「BJOI2014」大融合

    LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...

  8. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  9. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

随机推荐

  1. spring boot + dubbo开发遇到过的异常

    异常信息 NoClassDefFoundErrororg.apache.zookeeper.ClientCnxn$SendThread.run(ClientCnxn.java:1162) Sessio ...

  2. windows下docker启动.net core mvc随手记

    docker基本命令: 查看当前的版本docker--version查看本地所有镜像:docker images查看当前正在运行的所有容器docker ps停止某个容器:docker stop 容器I ...

  3. C#抽象类跟接口

    抽象类描述的是一个什么东西,属性. 抽象类是对类的抽象,描述是什么  抽象类,继承后重写接口描述的是他做什么,行为.接口是对行为的抽象,描述做什么  ,进行继承后实行接口

  4. 【Beta阶段】第十次Scrum Meeting!!!

    每日任务内容: 本次会议为第十次Scrum Meeting会议~ 本次会议为团队Beta阶段的最后一次会议!! 队员 今日完成任务 刘乾 #136(完成一半,今晨发布) 团队博客撰写 https:// ...

  5. Linux内核分析-创建新进程的过程

    分析Linux内核创建一个新进程的过程 task_struct结构体分析 struct task_struct{ volatile long state; //进程的状态 unsigned long ...

  6. 《Linux内核分析》第七周: 可执行程序的装载

    LINUX内核分析第七周学习总结--可执行程序的装载 杨舒雯(原创作品转载请注明出处) <Linux内核分析>MOOC课程http://mooc.study.163.com/course/ ...

  7. Ajax写成绩批量录入

    1.jsp,ajax的循环调用,必须要递归,否则会出错. <%@ page language="java" import="java.util.*" pa ...

  8. 第三个sprint冲刺第三阶段

    公测版:

  9. [问题解决]基于注解配置dubbo遇到ConnectionLoss for /dubbo/xxx问题解决

    今天升级spring版本的时候,同时升级dubbo的版本,采用的是dubbo的基于注解的配置方法,采用curator作为dubbo的客户端, curator版本为4.1.0,启动之后,发现一直报错 C ...

  10. React 表单受控组件

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...