题目分析:

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

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

时间复杂度$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. 每秒高达1.6亿次操作的并发键值存储库 FASTER 诞生

    FASTER 在过去十年中,云中的数据密集型应用程序和服务有了巨大的增长.数据在各种边设施(例如,设备,浏览器和服务器)上创建,并由云应用程序处理用来获得数据价值或做出决策.应用程序和服务可以处理收集 ...

  2. .NET Core 中正确使用 HttpClient 的姿势

    为了更方便在服务端调用 HTTP 请求,微软在 .NET Framework 4.x 的时候引入了 HttpClient.但 HttpClient 有很多严重问题,一直饱受诟病,比如 InfoQ 的这 ...

  3. hibernate多对多 一对多 及简单入门 主键生成策略

    Hibernate简单使用 入门 通过hibernate的 一对多 多对多轻松看懂hibernate配置 (不使用注解) hibernate对jdbc访问数据库的代码进行轻量级封装,简化重复代码 减少 ...

  4. Django的路由层

    U RL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代 ...

  5. c++入门之字符相关入门

    先上代码: # include "iostream" # include "string" //# define BYTE char//注意,这里没有分号,且# ...

  6. ARC 066D Xor Sum AtCoder - 2272 (打表找规律)

    Problem Statement You are given a positive integer N. Find the number of the pairs of integers u and ...

  7. echarts x轴 增加滚动条

    charts x轴 增加滚动条 在option 配置项中添加 [ dataZoom 中配置 ] 设置x轴滚动条 效果图: 动态拖动 以下参考代码 dataZoom配置 官网写法 option = { ...

  8. switch变种玩法

    标准版本: switch(表达式) { case 值1: 语句体1; break; case 值2: 语句体2; break; ... default: 语句体n+; break; } switch: ...

  9. MySQL 的两个特殊属性 unsigned与 zerofill

    1 unsigned unsigned 就是将数字类型无符号化, 例如 int 型的范围:-2^31 ~ 2^31 - 1,而unsigned int的范围:0 ~ 2^32.看起来unsigned ...

  10. 【学亮开讲】Oracle存储过程教学笔记(二)20181116

    --带出参的存储过程的创建和调用 create or replace procedure pro_owners_add1 ( v_name varchar2,--名称 v_addressid numb ...