「ZJOI2018」历史

前置知识

\(\text{LCT}\) 维护子树信息,考虑辅助树上一个节点的子树信息只是其代表的这一段链的信息,设 \(S(u)\) 为节点 \(u\) 的子树信息,那么在辅助树上我们维护的是:

\[S(u)=S(lson)+S(rson)+val(u)
\]

考虑它们的实际意义 \(lson\) 是 \(u\) 的父亲,\(rson\) 是 \(u\) 的重儿子,显然 \(S(lson)\) 是我们不需要的,而真正的辅助信息只算了节点本身和重儿子。

考虑按照这样算的话, \(u\) 的每一个轻儿子代表的子树信息都是合法的,那么可以再开一个 \(vs(u)\) 把所有轻儿子的 \(S\) 加上去。

\[S(u)=S(lson)+S(rson)+val(u)+vs(u)
\]

轻重链切换的时候暴力更新一下 \(vs(u)\) 即可,动态加边的话因为要影响虚边,要把两个点都 \(\text{makeroot}\) 来保证更新的 \(vs(u)\) 合法,删边的话因为保证了关系是重儿子,所以直接做就好了,\(access\) 切换轻重边的时候需要重新维护一下。

但这种做法适用范围不大,信息不可减就做不了,只能单点不断条重链修改,然而对这道题来说已经足够了。

解题思路

观察发现每个节点的贡献是独立的,同一个儿子内的连续多次崛起不会贡献新的代价。显然要最大化每个节点的贡献需要尽可能两次崛起位于不同的儿子的子树。

设节点 \(u\) 的子树 \(a_i\) 和为 \(sz(u)\) ,\(mson=\max(\max_{u\rightarrow v}sz(v), a(u))\) 。

如果 \(2mson\leq sz(u)\) ,那么显然可以构造出操作序列满足不会有连续相同,贡献就是 \(sz(u)-1\)。

否则可以贪心的考虑,尽可能多用 \(mson\) ,节点 \(u\) 的贡献就是 \(2(sz(u)-mson)\)。

如果 \(u\) 的一个儿子 \(v\) 满足 \(2sz(v)>sz(u)\) ,那么我们记 \(u\rightarrow v\) 这条边为重边,其余边为轻边,类似于树链剖分和 \(\text{LCT}\) 的结构。

然后我们可以得到一些基本推论。

  1. 一个节点向下只会至多有一条重边。
  2. 一个节点到根的路径上只会至多有 \(log_{na_i}\) 条轻边,因为每有一条轻边 \(sz(u)\) 至少减少二分之一。

观察发现每一次修改操作,路径上的重边仍旧是重边,所以贡献不变,路径上的轻边可能会发生改变,只需要找到这些轻边暴力改就好了。

前面说了这个结构和 \(\text{LCT}\) 很类似,只需要每条重链用辅助树维护,支持单点加求一个点在根为 \(1\) 时的子树和,以及找一个点到一条路径上的轻边。

前面两个要求 \(\text{LCT}\) 维护子树信息可以直接做,查询只需要类似 \(access\) 走一遍,但是不要强制断开原有的重边,而是对于每条轻边按照前置知识的方法更新子树和再判断,细节有点多。

复杂度的话,单次修改 \(\text{splay}\) 重链条数次,轻边条数是 \(O(log_{na_i})\) ,和正常的 \(\text{LCT}\) 没啥区别,套用那个的均摊分析就是 \(\mathcal O(nlogn)\) 。

code

/*program by mangoyang*/
#include<bits/stdc++.h>
#define inf (0x7f7f7f7f)
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
typedef long long ll;
using namespace std;
template <class T>
inline void read(T &x){
int ch = 0, f = 0; x = 0;
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
if(f) x = -x;
}
const int N = 800005;
vector<int> g[N];
int ch[N][2], fa[N], n, m;
ll vs[N], a[N], s[N], ans;
#define son(x) (ch[fa[x]][1] == x)
#define isr(x) (ch[fa[x]][0] != x && ch[fa[x]][1] != x)
inline void update(int u){ s[u] = s[ch[u][0]] + s[ch[u][1]] + a[u] + vs[u]; }
inline void rotate(int x){
int F = fa[x], G = fa[F], w = son(x);
if(!isr(F)) ch[G][son(F)] = x; fa[x] = G;
ch[F][w] = ch[x][w^1], fa[ch[x][w^1]] = F;
ch[x][w^1] = F, fa[F] = x, update(F);
}
inline void splay(int x){
for(int F = fa[x]; !isr(x); rotate(x), F = fa[x])
if(!isr(F)) rotate(son(F) == son(x) ? F : x);
update(x);
}
inline ll calc(int x, ll t, ll h){
return ch[x][1] ? ((t - h) << 1) : ((a[x] << 1) > t ? ((t - a[x]) << 1) : t - 1);
}
inline void access(int x, int w){
splay(x);
ll now = s[x] - s[ch[x][0]], mson = s[ch[x][1]];
ans -= calc(x, now, mson), s[x] += w, a[x] += w, now += w;
if((mson << 1) <= now) vs[x] += mson, ch[x][1] = mson = 0;
ans += calc(x, now, mson), update(x);
int c = x; x = fa[x];
for(; x; c = x, x = fa[x]){
splay(x);
ll now = s[x] - s[ch[x][0]], mson = s[ch[x][1]];
ans -= calc(x, now, mson), s[x] += w, vs[x] += w, now += w;
if((mson << 1) <= now) vs[x] += mson, ch[x][1] = mson = 0;
if((s[c] << 1) > now) vs[x] -= (mson = s[c]), ch[x][1] = c;
ans += calc(x, now, mson), update(x);
}
}
inline void dfs(int u){
s[u] = a[u];
for(int i = 0; i < (int) g[u].size(); i++)
if(g[u][i] != fa[u]) fa[g[u][i]] = u, dfs(g[u][i]), s[u] += s[g[u][i]];
for(int i = 0; i < (int) g[u].size(); i++)
if(g[u][i] != fa[u] && s[g[u][i]] * 2 > s[u]) ch[u][1] = g[u][i];
vs[u] = s[u] - a[u] - s[ch[u][1]];
ans += calc(u, s[u], s[ch[u][1]]);
}
int main(){
read(n), read(m);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1, x, y; i < n; i++){
read(x), read(y);
g[x].push_back(y), g[y].push_back(x);
}
dfs(1);
printf("%lld\n", ans);
for(int i = 1, x, y; i <= m; i++){
read(x), read(y), access(x, y);
printf("%lld\n", ans);
}
return 0;
}

「ZJOI2018」历史的更多相关文章

  1. 「ZJOI2018」历史(LCT)

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

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

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

  3. 题解 「ZJOI2018」历史

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

  4. LOJ #2434. 「ZJOI2018」历史(LCT)

    题意 click here 题解 我们首先考虑答案是个什么样的东西, 不难 发现每个点可以单独计算它的贡献. 令每个点 \(i\) 崛起次数为 \(a_i\) . 假设一个点子树的 \(\sum a_ ...

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

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

  6. 「ZJOI2018」胖(ST表+二分)

    「ZJOI2018」胖(ST表+二分) 不开 \(O_2\) 又没卡过去是种怎么体验... 这可能是 \(ZJOI2018\) 最简单的一题了...我都能 \(A\)... 首先我们发现这个奇怪的图每 ...

  7. Loj #2529. 「ZJOI2018」胖

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

  8. 「JOISC 2014 Day1」 历史研究

    「JOISC 2014 Day1」 历史研究 Solution 子任务2 暴力,用\(cnt\)记录每种权值出现次数. 子任务3 这不是一个尺取吗... 然后用multiset维护当前的区间,动态加, ...

  9. 「2014-2-26」Unicode vs. UTF-8 etc.

    目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ...

随机推荐

  1. LintCode 190: Next Permutation

    LintCode 190: Next Permutation 题目描述 给定一个若干整数的排列,给出按正数大小进行字典序从小到大排序后的下一个排列. 如果没有下一个排列,则输出字典序最小的序列. 样例 ...

  2. indexof()函数

    js 判断字符串是否包含某字符串,String对象中查找子字符,indexOf, 成功,返回索引值,失败返回 -1. 转载: http://www.cnblogs.com/fishtreeyu/arc ...

  3. Docker 配置国内镜像拉取中心,Configure docker to use faster registries in China.

    Networking in China is really bad when it comes to using some cloud based tools like docker, it's us ...

  4. CF 900B

    CF 900B Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u   Descript ...

  5. 基于scrapy的分布式爬虫抓取新浪微博个人信息和微博内容存入MySQL

    为了学习机器学习深度学习和文本挖掘方面的知识,需要获取一定的数据,新浪微博的大量数据可以作为此次研究历程的对象 一.环境准备   python 2.7  scrapy框架的部署(可以查看上一篇博客的简 ...

  6. Tutorial 5: Relationships & Hyperlinked APIs

    转载自:http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis/ Tutorial 5: ...

  7. 9.Python3标准库--数据压缩与归档

    ''' 尽管现代计算机系统的存储能力日益增长,但生成数据的增长是永无休止的. 无损(lossless)压缩算法以压缩或解压缩数据花费的时间来换取存储数据所需要的空间,以弥补存储能力的不足. Pytho ...

  8. Floyd_Warshall(任意两点之间的最短路)

    /* O(V^3) 案例: 1 2 2 1 3 5 2 3 1 */ #include <cstdio>#include <iostream>using namespace s ...

  9. 爬虫基础库之beautifulsoup的简单使用

    beautifulsoup的简单使用 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: ''' Beautiful Soup提供一些简单的.p ...

  10. 配置OpenCV+VS2013环境

    配置OpenCV+VS2013环境 准备工作 win7系统 下载opencv的windows编译版 安装vs2013 express 设定环境变量 按windows窗键输入path,选择第二个结果编辑 ...