【ZJOI 2018】 历史(lct)
历史
题目描述
九条可怜是一个热爱阅读的女孩子。
这个世界有 $n$ 个城市,这 $n$ 个城市被恰好 $n-1$ 条双向道路联通,即任意两个城市都可以互相到达。同时城市 $1$ 坐落在世界的中心,占领了这个城市就称霸了这个世界。
在最开始,这 $n$ 个城市都不在任何国家的控制之下,但是随着社会的发展,一些城市会崛起形成国家并夺取世界的霸权。为了方便,我们标记第 $i$ 个城市崛起产生的国家为第 $i$ 个国家。 在第 $i$ 个城市崛起的过程中,第 $i$ 个国家会取得城市 $i$ 到城市 $1$ 路径上所有城市的控制权。
新的城市的崛起往往意味着战争与死亡,若第 $i$ 个国家在崛起中,需要取得一个原本被国家 $j \; (j \neq i)$ 控制的城市的控制权,那么国家 $i$ 就必须向国家 $j$ 宣战并进行战争。
现在,可怜知道了,在历史上,第 $i$ 个城市一共崛起了 $a_{i}$ 次。但是这些事件发生的相对顺序已经无从考究了,唯一的信息是,在一个城市崛起称霸世界之前,新的城市是不会崛起的。
战争对人民来说是灾难性的。可怜定义一次崛起的灾难度为崛起的过程中会和多少不同的国家进行战争(和同一个国家进行多次战争只会被计入一次)。可怜想要知道,在所有可能的崛起顺序中,灾难度之和最大是多少。
同时,在考古学家的努力下,越来越多的历史资料被发掘了出来,根据这些新的资料,可怜会对 $a_{i}$ 进行一些修正。具体来说,可怜会对 $a_{i}$ 进行一些操作,每次会将 $a_{x}$ 加上 $w$。她希望在每次修改之后,都能计算得到最大的灾难度。
然而可怜对复杂的计算并不感兴趣,因此她想让你来帮她计算一下这些数值。 对题面的一些补充:
- 同一个城市多次崛起形成的国家是同一个国家,这意味着同一个城市连续崛起两次是不会和任何国家开战的:因为这些城市原来就在它的控制之下。
- 在历史的演变过程中,第 $i$ 个国家可能会有一段时间没有任何城市的控制权。但是这并不意味着第 $i$ 个国家灭亡了,在城市 $i$ 崛起的时候,第 $i$ 个国家仍然会取得 $1$ 到 $i$ 路径上的城市的控制权。
输入输出格式
输入格式:
第一行输入两个整数 $n$,$m$ 表示城市个数和操作个数。
第二行输入 $n$ 个整数表示 $a_{i}$ 的初始值。 接下来 $n − 1$ 行,每行输入两个整数 $u_{i}$, $v_{i}$, $(1 \leq u_{i}, v_{i} \leq n)$ 描述了一条道路。
接下来 $m$ 行每行输入两个整数 $x_{i}$, $w_{i}$ 表示将 $a_{x_{i}}$ 加上 $w_{i}$。
输出格式:
输出共 $m+1$ 行,第一行表示初始的 $a_{i}$ 的答案,接下来 $m$ 行每行表示这次修正后的答案。
样例一
input
5 3
1 1 1 1 1
1 2
1 3
2 4
2 5
2 1
3 1
4 1
output
6
7
9
10
explanation
在修正开始之前,如果按照所在城市 $4, 1, 5, 3, 2$ 的顺序崛起,那么依次会和 $0, 1, 2, 1, 2$ 个 国家进行战争。这时一共会产生 $6$ 对敌对关系。可以证明这是所有崛起顺序中的最大值。
限制与约定
时间限制:2s
空间限制:512MB
可以看出,问题的本质是,给出一棵树,给定每一个点的 $Access$ 次数,计算轻重链切换次数的最大值。
我们假设 $V_{i}$ 为每个节点最多能进行的 $Access$ 次数,$S_{i}$ 为 $i$ 点子树的$V$和。
我们可以先考虑没有修改的情况:
很显然,能改变 $x$ 点向下的边的轻重链的情况,当且仅当 $x$ 的子树中的某个节点进行的 $Access$ 操作。
可以发现,每一个点对答案的贡献是独立的,那设 $A_{x}$ 为 $x$ 点处切换轻重链的最大值,则 $Ans = \sum_{x=1}^{n} A_{x} $。
假设我们已经得到了一组以 $x$ 为子树的点的所有 $Access$ 操作的顺序,那它对 $x$ 点的贡献就是相邻两个点不同属于 $x$ 的某个亲儿子的子树中的数目。
我们可以任意调整它们进行 $Access$ 的顺序使得其贡献最大,设 $x$ 总共有 $m$ 个儿子,因此为了最大化 $x$ 处的轻重链切换次数,问题转化成了,有 $m+1$ 种颜色的小球(算上 $x$ 本身),第 $i$ 种颜色有 $S_{i}$ 个,要求把所有小球摆成一列,最大化左右小球的颜色不同的间隔数。易得,如果最大的某个 $S_{i} * 2$ 不超过 $\sum_{i=1}^{m+1}S_{i} + 1$,我们总能找到一种顺序,使得任意相邻的小球都颜色不同。即 $2 * \max(S_{i}) > \sum_{i=1}^{m+1}S_{i} + 1$ 时,$A_{x}$ 就是 $2*(\sum_{i=1}^{m+1}S_{i} − \max(S_{i}))$,否则 $Ax$ 就是 $\sum_{i=1}^{m+1}S_{i} − 1$。
于是我们可以 $O(n)$ 做无修改的情况了。
现在来考虑有修改的情况:
我们假设 $F$ 是 $i$ 点的父亲,如果 $A_{i} * 2 > A_{F} + 1$,我们就定义这条 $i$ 和 $F$ 的边为实边,否则为虚边。
很容易知道,一个点向下最多只有一条实边(可以类比树剖,虽然不是很一样),有可能没有。
如果我们修改的 $A_{i}$ 的值,则 $i$ 到根的路径上每一个节点的 $S_{i}$ 都会增加,易知,该路径上已经是实边的还会是实边,并且修改不会对实边的贡献造成影响,只要考虑那些虚边在修改后能否变成实边,以及虚边在修改后对答案造成的影响。
我们可以用 $LCT$ 维护该树,只是在 $Access$ 的时候并不是像原先那样切换轻重链,而是直接用虚实边,在原先 $Access$ 切换链的地方判断是否要改变虚实即可。
#include <cstdio> typedef long long LL; const int N = ; int n, m;
int L[N], R[N], P[N], hs[N];
LL Ans, A[N], sum[N], tag[N], va[N]; int yun, las[N], pre[N<<], to[N<<];
inline void Add(int a, int b) {
to[++yun]=b; pre[yun]=las[a]; las[a]=yun;
} inline int Isroot(int x) {
return L[P[x]]!=x && R[P[x]]!=x;
}
inline int Order(int x) {
return x==R[P[x]];
}
inline void Pushdown(int x) {
if (!tag[x] || !x) return;
sum[x]+=tag[x]; tag[L[x]]+=tag[x]; tag[R[x]]+=tag[x]; tag[x]=;
}
inline void Pushall(int x) {
if (!Isroot(x)) Pushall(P[x]); Pushdown(x);
}
inline void Rotate(int x) {
int Fa=P[x], Gr=P[Fa], d=Order(x), so=d? L[x]:R[x];
if (!Isroot(Fa)) (Order(Fa)? R[Gr]:L[Gr])=x; P[x]=Gr;
(d? R[Fa]:L[Fa])=so; P[so]=Fa;
(d? L[x]:R[x])=Fa; P[Fa]=x;
}
inline void Splay(int x) {
Pushall(x);
for (; !Isroot(x); Rotate(x))
if (!Isroot(P[x])) Rotate(Order(P[x])==Order(x)? P[x]:x);
}
inline int Get_root(int x) {
while (L[x]) Pushdown(x), x=L[x];
Pushdown(x);
return x;
} inline void Recalc(int x) {
Ans-=A[x];
A[x]=(hs[x])? (*(sum[x]-sum[hs[x]])):(sum[x]-);
if (va[x]*>sum[x]+) A[x]=*(sum[x]-va[x]);
Ans+=A[x];
} inline void Access(int x, int y) {
va[x]+=y;
for (int t=; x; t=x, x=P[x]) {
Splay(x);
sum[x]+=y; tag[L[x]]+=y; Pushdown(L[x]);
if (hs[x]) {
Pushall(hs[x]);
if (sum[hs[x]]*<=sum[x]+) hs[x]=R[x]=;
}
int son=Get_root(t);
if (sum[son]*>sum[x]+) hs[x]=son, R[x]=t;
Recalc(x);
}
} void Dfs_pre(int x, int Fa, int Ms=) {
P[x]=Fa; sum[x]=va[x];
for (int i=las[x]; i; i=pre[i]) if (to[i]!=Fa) {
Dfs_pre(to[i], x);
sum[x]+=sum[to[i]];
if (!Ms || sum[Ms]<sum[to[i]]) Ms=to[i];
}
if (sum[Ms]*>sum[x]+) hs[x]=Ms;
Recalc(x);
R[x]=hs[x];
} int main() {
scanf("%d%d", &n, &m);
for (int i=; i<=n; ++i) scanf("%lld", &va[i]);
for (int i=, x, y; i<n; ++i) scanf("%d%d", &x, &y), Add(x, y), Add(y, x);
Dfs_pre(, );
printf("%lld\n", Ans);
for (int x, y; m; --m) scanf("%d%d", &x, &y), Access(x, y), printf("%lld\n", Ans); return ;
}
【ZJOI 2018】 历史(lct)的更多相关文章
- [ZJOI 2018]历史
题意:给定一棵树和点的\(Access\)次数,求切换链的最大值. 考虑修改时实边与虚边的贡献,用\(LCT\)维护此树. // luogu-judger-enable-o2 #include< ...
- ZJOI 2018 一试记
ZJOI一试几天,天微冷,雨.倒是考试当天近午时分出了太阳. 开题前的一刻,心情反而平静了,窗外泛着淡金色的日光照进来,仿佛今天的我并不是所谓来冲击省队,而只是来经历一场洗礼. 开题了,虽然有一点小插 ...
- Luogu4338 ZJOI2018 历史 LCT、贪心
传送门 题意:在$N$个点的$LCT$中,最开始每条边的虚实不定,给出每一个点的$access$次数,求一种$access$方案使得每条边的虚实变换次数之和最大,需要支持动态增加某个点的$access ...
- P4338 [ZJOI2018]历史 LCT+树形DP
\(\color{#0066ff}{ 题目描述 }\) 这个世界有 n 个城市,这 n 个城市被恰好 \(n-1\) 条双向道路联通,即任意两个城市都可以 互相到达.同时城市 1 坐落在世界的中心,占 ...
- LOJ2434. 「ZJOI2018」历史 [LCT]
LOJ 思路 第一眼看似乎没有什么思路,试着套个DP上去:设\(dp_x\)表示只考虑\(x\)子树,能得到的最大答案. 合并的时候发现只有\(x\)这个点有可能做出新的贡献,而做出新贡献的时候必然是 ...
- 【ZJOI 2018】线图(树的枚举,hash,dp)
线图 题目描述 九条可怜是一个热爱出题的女孩子. 今天可怜想要出一道和图论相关的题.在一张无向图 $G$ 上,我们可以对它进行一些非常有趣的变换,比如说对偶,又或者说取补.这样的操作往往可以赋予一些传 ...
- [ZJOI 2018] 线图
别想多了我怎么可能会正解呢2333,我只会30分暴力(好像现场拿30分已经不算少了2333,虽然我局的30分不是特别难想). 首先求k次转化的点数显然可以变成求k-1次转化之后的边数,所以我们可以先让 ...
- NOIWC前的交流题目汇总
RT 2018.12.27 i207M:BZOJ 4695 最假女选手 以维护最大值为例,记录最大值和严格次大值和最大值的出现次数,然后取min的时候递归到小于最大值但大于次大值修改,这个就是最重要的 ...
- 「ZJOI2018」历史(LCT)
「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...
随机推荐
- Lwip:原生态的Linux socket应用如何移植到Lwip上
lwIP - A Lightweight TCP/IP stack 在上一篇中,我们了解到在OpenFastPath上如何移植原生态的Linux Socket应用程序,那么,对于另外一个老牌的小型TC ...
- 《how tomcat works》阅读笔记 - 2 - 门面设计模式,避免强制转换
在第二章 2.3节中 try { servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) request ...
- Git----01介绍&下载&安装&创建本地仓库
一.Git介绍 1.0.Git是分布式版本控制工具 1.1.历史 Linux 内核开源项目有着为数众广的参与者.绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2 ...
- NO.7:自学python之路------类的方法、异常处理、socket网络编程
引言 我visual studio 2017就算体积巨大.启动巨慢.功能简陋也不会安装PyCharm的,嘿呀,真香.好吧,为了实现socket网络编程,更换了软件. 正文 静态方法 只是在名义上归类管 ...
- 升级salt导致进程kill问题记录
重启salt-minion导致由salt启动的进程kill问题排查 作者:耀耀 blog:https://www.liuyao.me 环境 服务器系统为centos6及centos7 服务器服务进程都 ...
- [奇葩问题] Error Domain=NSURLErrorDomain Code=-1003
问题描述: 新上线的产品,ios同事拿着一串报错来找我,日志如下:err =Error Domain=NSURLErrorDomain Code=-1003 "未能找到使用指定主机名的服务器 ...
- hive对于lzo文件处理异常Caused by: java.io.IOException: Compressed length 842086665 exceeds max block size 67108864 (probably corrupt file)
hive查询lzo数据格式文件的表时,抛 Caused by: java.io.IOException: Compressed length 842086665 exceeds max block s ...
- Java 的 java_home, path, classpath
java_home: 指定 jdk 的安装目录. 第三方软件 Eclipse / Tomcat 在 java_home 指定的目录下查找安装好的 jdk. path: 配置 jdk 的安装目录.在命令 ...
- 在Gulp中使用BrowserSync
博客已迁移至http://zlwis.me. 很早就听说过BrowserSync,也看过一些相关文章,可就是没用过.之前一直在用Gulp开发项目,每次编写完Sass后还要用按F5刷新页面看效果,想想也 ...
- 个人作业Week7
1.在做个人项目的时候,由于很久都没有写这么大的程序了,对程序的感觉还没有恢复,因此,没能完全完成个人项目.现在回去看个人项目的代码(针对完成的代码来看),完全就是一个大泥球,代码的结构性太差,基本上 ...