Description

九条可怜是一个热爱阅读的女孩子。

这段时间,她看了一本非常有趣的小说,这本小说的架空世界引起了她的兴趣。

这个世界有n个城市,这n个城市被恰好n?1条双向道路联通,即任意两个城市都可以互相到达。同时城市1坐落在世

界的中心,占领了这个城市就称霸了这个世界。

在最开始,这n个城市都不在任何国家的控制之下,但是随着社会的发展,一些城市会崛起形成国家并夺取世界的

霸权。为了方便,我们标记第i个城市崛起产生的国家为第i个国家。在第i个城市崛起的过程中,第i个国家会取得

城市i到城市1路径上所有城市的控制权。

新的城市的崛起往往意味着战争与死亡,若第i个国家在崛起中,需要取得一个原本被国家j(j!=i)控制的城市的控

制权,那么国家i就必须向国家j宣战并进行战争。

现在,可怜知道了,在历史上,第i个城市一共崛起了ai次。但是这些事件发生的相对顺序已经无从考究了,唯一

的信息是,在一个城市崛起称霸世界之前,新的城市是不会崛起的。战争对人民来说是灾难性的。可怜定义一次崛

起的灾难度为崛起的过程中会和多少不同的国家进行战争(和同一个国家进行多次战争只会被计入一次)。可怜想

要知道,在所有可能的崛起顺序中,灾难度之和最大是多少。

同时,在考古学家的努力下,越来越多的历史资料被发掘了出来,根据这些新的资料,可怜会对ai进行一些修正。

具体来说,可怜会对ai进行一些操作,每次会将ax加上w。她希望在每次修改之后,都能计算得到最大的灾难度。

然而可怜对复杂的计算并不感兴趣,因此她想让你来帮她计算一下这些数值。

对题面的一些补充:

1:同一个城市多次崛起形成的国家是同一个国家,这意味着同一个城市连续崛起两次是不会和任何国家开战的:因

为这些城市原来就在它的控制之下。

2:在历史的演变过程中,第i个国家可能会有一段时间没有任何城市的控制权。但是这并不意味着第i个国家灭亡了

,在城市i崛起的时候,第i个国家仍然会取得1到i路径上的城市的控制权

Solution

实际上崛起就是一个 \(access\) 的过程,同一 \(splay\) 中的城市被同一个国家占领

要最大化的就是轻重边切换的次数

考虑最优决策:

每一个点被占领的次数是独立的,之和其子树内的点 \(access\) 的顺序有关,我们可以分开算贡献

最优决策肯定是不断的在子树内切换,使得这个点被占领的次数尽可能多

如果设 \(s[x]\) 表示 \(x\) 子树内的点的 \(a[i]\) 之和,\(sum\) 表示 \(\sum s[son]\),\(mx\) 表示 \(max(s[son])\)

那么这个点最多被占领: \(min(sum-1,2*(sum-mx),2*(sum-a[x]))\)

\(dfs\) 一遍就可以有 \(30\) 分了

现在只需要优化修改操作了

修改只会影响到这个点到根的路径上的点的贡献

我们把 \(s[son]*2>s[x]\) 的儿子作为重儿子,那么就会得到轻重链剖分

我们按照 \(access\) 那样暴力改上去,复杂度就和 \(access\) 是一样的了

和普通的 \(access\) 不同的是,虚边不一定会变成实边,但虚边个数是 \(log\) 的,所以复杂度是对的

\(LCT\) 维护每一个点的权值或者维护虚子树都可以做,不过维护虚子树就不需要打 \(lazy\) 了

\(30\)分\(.cpp\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
int n,Q,a[N],head[N],nxt[N*2],to[N*2],num=0;ll ans=0,s[N],mx[N];
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void dfs(int x,int last){
mx[x]=s[x]=a[x];
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(u==last)continue;
dfs(u,x);
mx[x]=max(mx[x],s[u]);
s[x]+=s[u];
}
ans+=min(s[x]-1,2*(s[x]-mx[x]));
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.ans","w",stdout);
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int x,y;
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
link(x,y);link(y,x);
}
dfs(1,1);
cout<<ans<<endl;
while(Q--){
scanf("%d%d",&x,&y);
a[x]+=y;ans=0;
dfs(1,1);
cout<<ans<<endl;
}
return 0;
}

\(100\)分\(.cpp\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<class T>void gi(T &w){
char ch=getchar();w=0;
while(ch>'9' || ch<'0')ch=getchar();
while(ch>='0' && ch<='9')w=w*10+ch-'0',ch=getchar();
}
const int N=4e5+10;
int n,Q,ch[N][2],head[N],nxt[N*2],num=0,to[N*2];
int fa[N],k[N];ll ans=0,xu[N],s[N],a[N];
inline void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
inline void dfs(int x,int last){
s[x]=a[x];
ll mx=a[x];int y=x;
for(int i=head[x],u;i;i=nxt[i]){
if((u=to[i])==last)continue;
fa[u]=x;dfs(u,x);s[x]+=s[u];
if(s[u]>mx)mx=s[u],y=u;
}
xu[x]=s[x];
if(mx<<1>s[x]){
ans+=(s[x]-mx)<<1;
if(x!=y)ch[x][1]=y,xu[x]-=s[y];
else k[x]=1;
}
else ans+=s[x]-1,k[x]=2;
}
inline bool isrt(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
inline void upd(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+xu[x];}
inline void rotate(int x){
int y=fa[x];bool t=ch[y][1]==x;
ch[y][t]=ch[x][!t];fa[ch[y][t]]=y;
ch[x][!t]=y;fa[x]=fa[y];
if(!isrt(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
fa[y]=x;upd(y);upd(x);
}
inline void splay(int x){
while(!isrt(x)){
int y=fa[x],p=fa[y];
if(isrt(y))rotate(x);
else if((ch[p][0]==y)==(ch[y][0]==x))rotate(y),rotate(x);
else rotate(x),rotate(x);
}
}
inline void access(int x,int t){
int y=0;ll v=0;
while(x){
splay(x);
v=s[x]-s[ch[x][0]];
if(k[x]==2)ans-=v-1;
else ans-=(v-(k[x]?a[x]:s[ch[x][1]]))<<1;
v+=t;s[x]+=t;xu[x]+=t;a[x]+=(y?0:t);
if(s[y]<<1>v)xu[x]+=s[ch[x][1]],xu[x]-=s[ch[x][1]=y]; if(s[ch[x][1]]<<1>v)ans+=(v-s[ch[x][1]])<<1,k[x]=0;
else{
if(ch[x][1])xu[x]+=s[ch[x][1]],ch[x][1]=0;
if(a[x]<<1>v)ans+=(v-a[x])<<1,k[x]=1;
else k[x]=2,ans+=v-1;
}
x=fa[y=x];
}
printf("%lld\n",ans);
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
int x,y;
gi(n);gi(Q);
for(int i=1;i<=n;i++)gi(a[i]);
for(int i=1;i<n;i++){
gi(x);gi(y);
link(x,y);link(y,x);
}
dfs(1,1);
cout<<ans<<endl;
while(Q--)gi(x),gi(y),access(x,y);
return 0;
}

bzoj 5212: [Zjoi2018]历史的更多相关文章

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

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

  2. [ZJOI2018]历史

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

  3. Luogu4338 ZJOI2018 历史 LCT、贪心

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

  4. BZOJ 5308 [ZJOI2018] Day2T2 胖 | 二分 ST表

    题目链接 LOJ 2529 BZOJ 5308 题解 这么简单的题 为什么考场上我完全想不清楚 = = 对于k个关键点中的每一个关键点\(a\),二分它能一度成为哪些点的最短路起点(显然这些点在一段包 ...

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

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

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

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

  7. BZOJ5212 ZJOI2018历史(LCT)

    首先相当于最大化access的轻重边交换次数. 考虑每个点作为战场(而不是每个点所代表的国家与其他国家交战)对答案的贡献,显然每次产生贡献都是该点的子树内(包括自身)此次access的点与上次acce ...

  8. [BZOJ5212][ZJOI2018]历史

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

  9. bzoj 5308: [Zjoi2018]胖

    Description Cedyks是九条可怜的好朋友(可能这场比赛公开以后就不是了),也是这题的主人公. Cedyks是一个富有的男孩子.他住在著名的ThePLace(宫殿)中. Cedyks是一个 ...

随机推荐

  1. C语言程序设计(基础)- 第2周作业

    1.阅读提问的智慧,要求仔细阅读链接内容,用自己的话描述你的收获,并举例子说明应该如何提问. 2.所有同学请在自己电脑上配置git.编译器(win10 系统的话就Dev-C++).翻译软件,十一回校后 ...

  2. C语言第九次作业

    一.PTA实验作业 题目1:统计大于等于平均分人数 1. 本题PTA提交列表 2.设计思路 float i为循环变量,sum=0,count=0来表示所求人数 float *p=s来储存首地址 for ...

  3. Linux下进程间通信--消息队列

    消息队列的定义遍地都是,不想移驾,请看下文: 一.定义: 消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法. 每个数据块都被认 为是有一个类型,接收者进程接收的数据块可以有不同的类型值.我 ...

  4. 多种在线地图综合对比,Google,必应,arcgis Online...

    不同网络地图的对比 天地图 坐标系:WGS84 地图配色:   POI数量:丰富      有无建筑:有 地图特点:天地图按照国家标准进行配图,道路.水系.植被等图层用对应颜色渲染, POI信息丰富, ...

  5. aix 6.1系统怎么安装?这里有详细图文教程

    今年六月,我们公司出现了一次非常严重的数据丢失的事故.生产服务器崩溃导致所有的业务都陷于停滞,而且由于涉及到公司机密又无法贸然到数据恢复公司进行恢复,可是自己又无法解决.权衡利弊还是决定找一家有保密资 ...

  6. python使用tesseract-ocr完成验证码识别(模型训练和使用部分)

    一.Tesseract训练 大体流程为:安装jTessBoxEditor -> 获取样本文件 -> Merge样本文件 –> 生成BOX文件 -> 定义字符配置文件 -> ...

  7. Gson解析Json数组

    需求:从steam官网获取英雄数据,即为Json数据,并导入到本地数据库 Json数据是这样的 { "result": { "heroes": [ { &quo ...

  8. JAVA_SE基础——51.内部类

    在Java中,允许在一个类的内部定义类,这样的类称作内部类,这个内部类所在的类称作外部类.根据内部类的位置.修饰符和定义的方式可分为成员内部类.静态内部类.方法(局部内部类)内部类. 内部类:一个类定 ...

  9. Web Api 接收图片

    public async Task<HttpResponseMessage> Upload() { if (!Request.Content.IsMimeMultipartContent( ...

  10. wordpress怎么禁止文章复制

    登陆你的网站后台--点击菜单栏的"外观"--点击"编辑"--在右侧,找到footer.php,打开它--在</body>之前加入以下代码: 1.禁止 ...