题目分析:

解决了上次提到的《切树游戏》后,这道题就是一道模板题。

注意我们需要用堆维护子重链的最大值。这样不会使得复杂度变坏,因为每个重链我们只考虑一个点。

时间复杂度$O(nlog^2n)$

代码:

 #include<bits/stdc++.h>
using namespace std; typedef long long ll; const int maxn = ; int n,m;
int v[maxn];
vector<int> g[maxn];
int fa[maxn],dep[maxn],sz[maxn],son[maxn],top[maxn],tail[maxn];
int where[maxn],number[maxn],num;
ll TOT[maxn]; struct Priority_queue{
priority_queue <ll,vector<ll>,less<ll> > pq,del;
void Insert(ll now){pq.push(now);}
void Erase(ll now){del.push(now);}
ll Top(){
while(!del.empty()&&pq.top() == del.top()) pq.pop(),del.pop();
return pq.top();
}
int Size(){return pq.size()-del.size();}
}PQ[maxn]; struct node{ll L,R,D,C;}T[maxn<<]; void push_up(int now){
T[now].L = max(T[now<<].L,T[now<<].C+T[now<<|].L);
T[now].R = max(T[now<<|].R,T[now<<|].C+T[now<<].R);
T[now].D = max(max(T[now<<].D,T[now<<|].D),T[now<<].R+T[now<<|].L);
T[now].C = T[now<<].C+T[now<<|].C;
} node merge(node alpha,node beta){
node gamma; gamma.L = max(alpha.L,alpha.C+beta.L);
gamma.R = max(beta.R,beta.C+alpha.R);
gamma.D = max(max(alpha.D,beta.D),alpha.R+beta.L);
gamma.C = alpha.C+beta.C;
return gamma;
} char readchar(){
char ch = getchar(); while(ch != 'M' && ch != 'Q') ch = getchar();
return ch;
} void read(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&v[i]);
for(int i=;i<n;i++){
int x,y; scanf("%d%d",&x,&y);
g[x].push_back(y); g[y].push_back(x);
}
} void dfs1(int now,int f,int dp){
fa[now] = f; dep[now] = dp;
for(int i=;i<g[now].size();i++){
if(g[now][i] == f) continue;
dfs1(g[now][i],now,dp+);
sz[now] += sz[g[now][i]];
if(son[now]==||sz[son[now]]<sz[g[now][i]])son[now]=g[now][i];
}
sz[now]++;
if(son[now]) tail[now] = tail[son[now]];
else tail[now] = now;
} void dfs2(int now,int tp){
top[now] = tp;number[now] = ++num; where[num] = now;
if(son[now]) dfs2(son[now],tp);
for(int i=;i<g[now].size();i++){
if(g[now][i] == fa[now] || g[now][i] == son[now]) continue;
dfs2(g[now][i],g[now][i]);
}
} void Modify(int now,int tl,int tr,int place){
if(tl == tr){
tl = where[tl];
T[now].C = TOT[tl] + v[tl];
T[now].L = max(0ll,TOT[tl]+v[tl]); T[now].R = T[now].L;
if(PQ[tl].Size()) T[now].D = max(PQ[tl].Top(),T[now].L);
else T[now].D = T[now].L;
}else{
int mid = (tl+tr)/;
if(place <= mid) Modify(now<<,tl,mid,place);
else Modify(now<<|,mid+,tr,place);
push_up(now);
}
} node Query(int now,int tl,int tr,int l,int r){
if(tl >= l && tr <= r) return T[now];
int mid = (tl+tr)/;
if(r <= mid) return Query(now<<,tl,mid,l,r);
if(l > mid) return Query(now<<|,mid+,tr,l,r);
return merge(Query(now<<,tl,mid,l,r),Query(now<<|,mid+,tr,l,r));
} void dfs3(int now){
if(son[now]) dfs3(son[now]);
for(int i=;i<g[now].size();i++){
int mp = g[now][i];
if(mp == fa[now] || mp == son[now]) continue;
dfs3(mp);
PQ[now].Insert(Query(,,n,number[mp],number[tail[mp]]).D);
}
Modify(,,n,number[now]);
if(top[now] == now){
long long data = Query(,,n,number[now],number[tail[now]]).L;
if(data > && fa[now]) TOT[fa[now]]+=data;
}
} void work(){
dfs1(,,);
dfs2(,);
dfs3();
for(int i=;i<=m;i++){
char ch = readchar();
if(ch == 'M'){
int x,y; scanf("%d%d",&x,&y);
stack<int> sta; int now = top[x];
while(fa[now]) sta.push(now),now = top[fa[now]];
while(!sta.empty()){
int mp = sta.top();sta.pop();
node res = Query(,,n,number[mp],number[tail[mp]]);
PQ[fa[mp]].Erase(res.D);
if(res.L > ) TOT[fa[mp]]-=res.L;
Modify(,,n,number[fa[mp]]);
}
now = x; v[x] = y;
while(now){
Modify(,,n,number[now]);
now = top[now];
node res = Query(,,n,number[now],number[tail[now]]);
if(res.L > && fa[now]) TOT[fa[now]]+=res.L;
PQ[fa[now]].Insert(res.D);
now= fa[now];
}
}else{
int x; scanf("%d",&x);
long long ans = Query(,,n,number[x],number[tail[x]]).D;
printf("%lld\n",ans);
}
}
} int main(){
read();
work();
return ;
}

BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】的更多相关文章

  1. 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp

    题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...

  2. 2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)

    传送门 题意:支持单点修改,维护子树里的最大连通子块和. 思路: 扯皮: bzojbzojbzoj卡常差评. 网上的题解大多用了跟什么最大子段和一样的转移方法. 但是我们实际上是可以用矩阵转移的传统d ...

  3. [bzoj4712]洪水 线段树+树链剖分维护动态dp+二分

    Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地爬 ...

  4. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  5. bzoj5210最大连通子块和 (动态dp+卡常好题)

    卡了一晚上,经历了被卡空间,被卡T,被卡数组等一堆惨惨的事情之后,终于在各位大爹的帮助下过了这个题qwqqq (全网都没有用矩阵转移的动态dp,让我很慌张) 首先,我们先考虑一个比较基础的\(dp\) ...

  6. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  7. BZOJ4538:[HNOI2016]网络(树链剖分,堆)

    Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...

  8. [树链剖分]BZOJ3589动态树

    题目描述 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0: 这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1: 小明希望你求出几条树枝上 ...

  9. bzoj5210 最大连通子块和 动态 DP + 堆

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5210 题解 令 \(dp[x][0]\) 表示以 \(x\) 为根的子树中的包含 \(x\) ...

随机推荐

  1. 失物找寻APP软件需求规格说明书——第三次团队作业

    ⭐对于软件需求规格说明书的理解 在没写这份软件需求规格说明书的时候我们组成员都不是很理解它的必要性,当然,写完之后才知道它的作用. 软件需求说明书的存在是为了使用户和软件开发者双方对该软件的初始规定有 ...

  2. WebClient, HttpClient, HttpWebRequest ,RestSharp之间的区别与抉择

    NETCore提供了三种不同类型用于生产的REST API: HttpWebRequest;WebClient;HttpClient,开源社区创建了另一个名为RestSharp的库.如此多的http库 ...

  3. DOM操作 JS事件 节点增删改查

    --------------------------习惯是社会的巨大的飞轮和最可贵的维护者.——威·詹姆斯 day 49 [value属性操作] <!DOCTYPE html><ht ...

  4. TCP/IP 协议 OSI七层协议

    ------------------你来自何处并不重要,重要的是你要去往何方,人生最重要的不是所站的位置,而是所去的方向.人只要不失去方向,就永远不会失去自己! day 27 # # -------- ...

  5. Leetcode 665. Non-decreasing Array(Easy)

    Given an array with n integers, your task is to check if it could become non-decreasing by modifying ...

  6. Vue2.0 搭建Vue脚手架(vue-cli)

    介绍 Vue.js是一套构建用户界面的渐进式框架.Vue 只关注视图层,采用自底向上增量开发的设计.Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 阅读之前需要了解的知 ...

  7. 学习yii2.0——依赖注入

    依赖注入 依赖注入是一种设计模式,可以搜索“php依赖注入”,这里不阐述了. yii框架的依赖注入 Yii 通过 yii\di\Container 类提供 DI 容器特性. 它支持如下几种类型的依赖注 ...

  8. 【学习总结】C-翁恺老师-入门-总

    2019-1-2 翁恺老师C入门视频-启程 代码详见GitHub: 目录 第0周:程序设计与C语言 第1周:计算 第2周:判断 第3周:循环 第4周:循环控制 第5周:数据类型 第6周:函数 第7周: ...

  9. java kill thread command line

    multithreading - How do you kill a Thread in Java? - Stack Overflowhttps://stackoverflow.com/questio ...

  10. 移动端和PC端页面常用的弹出层

    我们在页面的时候,很多时候用到了弹出层,消息提醒,确认框等等,统一样式的弹出框可以使页面更加优美.在此,我整理一下我们项目的移动端和PC端页面常用的弹出层. 一.移动端 我们需在页面引入弹出框的样式和 ...