首先相当于最大化access的轻重边交换次数。

  考虑每个点作为战场(而不是每个点所代表的国家与其他国家交战)对答案的贡献,显然每次产生贡献都是该点的子树内(包括自身)此次access的点与上次access的点在该点不同儿子的子树内。假设得到了最后的崛起序列,可以发现相互不包含的子树的贡献是相互独立的,只是内部交换而不交换他们的相对顺序,对答案没有任何影响。

  那么现在只需要考虑最大化某点的贡献,显然应该让不同儿子的子树内的点尽量交替access。设各点子树的Σai为si,那么当不存在2sson>si时,该点贡献为si-1,否则为2(si-max{sson})。于是如果没有修改,对每个子树求出s就能计算答案了。

  接下来考虑怎么修改。显然修改某点会影响该点到根的路径上的所有点的贡献。因为贡献与2sson>si的儿子有特殊的关系,考虑将其视为preferred child,把子树根与该儿子的边设为重边,如果不存在或根自身就是最大的就与儿子全部连轻边。同时注意到修改只会使某点的ai增加,如果其本来就是preferred child,修改后仍然是,并且可以发现这不会对答案造成影响;如果不是的话可能会存在轻重边切换的情况,其自身变为preferred child,但无论如何这说明这棵子树原来的sson不足其父亲si的一半,而这显然只能存在log次。所以用一棵不会动的LCT做一个真正的access就能修改了,可以打个lazy避免维护子树。感觉有一堆情况事实上最后也没啥要讨论的。

  虽然写了一年但是1A感觉爽爆啊?

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define ll long long
#define N 400010
#define lson tree[k].ch[0]
#define rson tree[k].ch[1]
#define lself tree[tree[k].fa].ch[0]
#define rself tree[tree[k].fa].ch[1]
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,m,p[N],t;
ll ans;
struct data{int to,nxt;
}edge[N<<];
struct data2{int ch[],fa;ll x,s,lazy,ans;
}tree[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k,int from)
{
tree[k].s=tree[k].x;ll mx=tree[k].x;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from)
{
tree[edge[i].to].fa=k;
dfs(edge[i].to,k);
tree[k].s+=tree[edge[i].to].s;
mx=max(mx,tree[edge[i].to].s);
}
if (*mx<=tree[k].s) tree[k].ans=tree[k].s-;
else
{
tree[k].ans+=tree[k].s-mx<<;
for (int i=p[k];i;i=edge[i].nxt)
if (edge[i].to!=from&&tree[edge[i].to].s==mx) {tree[k].ch[]=edge[i].to;break;}
}
ans+=tree[k].ans;
}
void add(int k,ll x){if (k) tree[k].s+=x,tree[k].lazy+=x;}
void down(int k){if (tree[k].lazy) add(lson,tree[k].lazy),add(rson,tree[k].lazy),tree[k].lazy=;}
int whichson(int k){return rself==k;}
bool isroot(int k){return lself!=k&&rself!=k;}
void push(int k){if (!isroot(k)) push(tree[k].fa);down(k);}
void move(int k)
{
int fa=tree[k].fa,gf=tree[fa].fa,p=whichson(k);
if (!isroot(fa)) tree[gf].ch[whichson(fa)]=k;tree[k].fa=gf;
tree[fa].ch[p]=tree[k].ch[!p],tree[tree[k].ch[!p]].fa=fa;
tree[k].ch[!p]=fa,tree[fa].fa=k;
}
void splay(int k)
{
push(k);
while (!isroot(k))
{
int fa=tree[k].fa;
if (!isroot(fa))
if (whichson(fa)^whichson(k)) move(k);
else move(fa);
move(k);
}
}
void access(int k,int x)
{
tree[k].x+=x;
for (int t=;k;)
{
splay(k);
if (rson)
{
int p=rson;for (;tree[p].ch[];p=tree[p].ch[]) down(p);
splay(p);
while (!isroot(k)) move(k);
}
tree[k].s+=x;
ans-=tree[k].ans;
if ((tree[rson].s<<)<=tree[k].s) rson=;
if ((tree[t].s<<)>tree[k].s) rson=t,tree[k].ans=tree[k].s-tree[t].s<<;
else if ((tree[k].x<<)>tree[k].s) tree[k].ans=tree[k].s-tree[k].x<<;
else if ((tree[rson].s<<)>tree[k].s) tree[k].ans=tree[k].s-tree[rson].s<<;
else tree[k].ans=tree[k].s-;
ans+=tree[k].ans;
add(lson,x);
for (;lson;k=lson) down(k);
splay(k);
t=k;k=tree[k].fa;
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5212.in","r",stdin);
freopen("bzoj5212.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),m=read();
for (int i=;i<=n;i++) tree[i].x=read();
for (int i=;i<n;i++)
{
int x=read(),y=read();
addedge(x,y),addedge(y,x);
}
dfs(,);cout<<ans<<endl;
for (int i=;i<=m;i++)
{
int x=read(),y=read();
access(x,y);
printf(LL,ans);
}
return ;
}

BZOJ5212 ZJOI2018历史(LCT)的更多相关文章

  1. Luogu4338 ZJOI2018 历史 LCT、贪心

    传送门 题意:在$N$个点的$LCT$中,最开始每条边的虚实不定,给出每一个点的$access$次数,求一种$access$方案使得每条边的虚实变换次数之和最大,需要支持动态增加某个点的$access ...

  2. P4338 [ZJOI2018]历史 LCT+树形DP

    \(\color{#0066ff}{ 题目描述 }\) 这个世界有 n 个城市,这 n 个城市被恰好 \(n-1\) 条双向道路联通,即任意两个城市都可以 互相到达.同时城市 1 坐落在世界的中心,占 ...

  3. [BZOJ5212][ZJOI2018]历史

    传送门(洛谷) 人生第一道九条可怜……神仙操作…… 看着题解理解了一个早上才勉强看懂怎么回事…… 简化一下题目就是:已知每一个点access的总次数,求一个顺序使虚实边转化的次数最多 考虑一下,对于x ...

  4. 【BZOJ5212】[ZJOI2018]历史(Link-Cut Tree)

    [BZOJ5212][ZJOI2018]历史(Link-Cut Tree) 题面 洛谷 BZOJ 题解 显然实际上就是给定了一棵树和每个点被\(access\)的次数,求解轻重链切换的最大次数. 先考 ...

  5. [ZJOI2018]历史

    [ZJOI2018]历史 最大化access轻重链的切换次数 考虑一个点的贡献,即它交换重儿子的次数 发现这个次数只和它自己ai以及每个儿子的子树次数和有关. 一个关键的事实是: 我们可以自上而下进行 ...

  6. 【BZOJ5212】[ZJOI2018] 历史(LCT大黑题)

    点此看题面 大致题意: 给定一棵树每个节点\(Access\)的次数,求最大虚实链切换次数,带修改. 什么是\(Access\)? 推荐你先去学一学\(LCT\)吧. 初始化(不带修改的做法) 首先考 ...

  7. [ZJOI2018]历史(LCT)

    这篇还发了洛谷题解 [Luogu4338] [BZOJ5212] 题解 题意 给出一棵树,给定每一个点的 \(access\) 次数,计算轻重链切换次数的最大值,带修改. 先考虑不带修改怎么做 假设 ...

  8. 洛谷P4338 [ZJOI2018]历史(LCT,树形DP,树链剖分)

    洛谷题目传送门 ZJOI的考场上最弱外省选手T2 10分成功滚粗...... 首先要想到30分的结论 说实话Day1前几天刚刚刚掉了SDOI2017的树点涂色,考场上也想到了这一点 想到了又有什么用? ...

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

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

随机推荐

  1. 在使用Reference Source调试.Net 源代码时如何取消optimizations(代码优化)-翻译

    在使用PDB调试XAF时,发现好多变量都看不到.都被优化掉了. 下面的方法可以解决. 当你在使用Reference Source functionality in VS 2008 调试.Net 的源代 ...

  2. BLACKPYTHON学习(一)

    C/S结构了解 所谓的C/S就是客户端(client)和服务器端(server)的简称,也就是在基于这个的基础上编写相关的代码:一个就是客户端一个就是服务端. TCP(client) 客户端编写 #因 ...

  3. Java+Netty实现的RESTful框架--netty-rest-server

    在工作中用Netty做了几个服务,感觉Netty做出来的程序性能好,资源占用少,但是实现Http服务比较麻烦,于是就参考Spring MVC的注解基于Netty实现了一个轻量级的RESTful框架. ...

  4. Linux入门基础(二):Linux磁盘及文件管理系统

    磁盘管理 fdisk分区工具 只支持MBR分区 fdisk命令只有root用户能用 fdisk -l 列出所有安装磁盘及分区信息 fdisk /dev/sda (操作磁盘,按m可列出帮助界面,常用的操 ...

  5. python的类和对象2(self参数)

    python的类和对象2(self参数) 1.python里面对象的方法都会有self参数,它就相当于C++里面的this指针:绑定方法,据说有了这个参数,Python 再也不会傻傻分不清是哪个对象在 ...

  6. swap分区和内存

    1  查看swap 空间大小(总计):      # free -m          默认单位为k, -m 单位为M                total       used       fr ...

  7. python初学者随笔Week2

    一.集合 去重,把一个列表变成集合,自动去重 关系测试,测试两组数据的交集,并集,差集关系 集合是无序的 集合的操作: list_1 = [1,4,5,7,3,6,7,9] list_1 = set( ...

  8. linux压缩相关

    tar命令 tar是打包,即把好多东西放在一个大文件里面,之后再压缩:当然也可以解包 tar的几个参数说明: -c 创建一个新的包 -x 将包里的文件还原出来 -t 显示包内文件的列表 -f 指定要处 ...

  9. win10浏览器访问vmware中ubuntu开启的某个服务端口出现的问题

    问题描述 1. win10系统中浏览器能正常访问  ubuntu中nginx服务器的80端口, 但是不能访问8082 问题原因 ubuntu 防火墙默认没有启用 8082端口, 需要开启这个端口号 解 ...

  10. easyui panel异步获取后台数据在前台显示

    我在使用easyui的时候,想做一个向下图所示的效果,这个panel的样式已经做好了,想从后台异步获取json数据,然后填入到文本框中,不知道哪位大神能给点指导?万分感谢! 放入表单中,使用form对 ...