BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】
题目分析:
解决了上次提到的《切树游戏》后,这道题就是一道模板题。
注意我们需要用堆维护子重链的最大值。这样不会使得复杂度变坏,因为每个重链我们只考虑一个点。
时间复杂度$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】的更多相关文章
- 【bzoj5210】最大连通子块和 树链剖分+线段树+可删除堆维护树形动态dp
题目描述 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块和. 其中,一棵子树的最大连通子块和指的是:该子树 ...
- 2019.02.15 bzoj5210: 最大连通子块和(链分治+ddp)
传送门 题意:支持单点修改,维护子树里的最大连通子块和. 思路: 扯皮: bzojbzojbzoj卡常差评. 网上的题解大多用了跟什么最大子段和一样的转移方法. 但是我们实际上是可以用矩阵转移的传统d ...
- [bzoj4712]洪水 线段树+树链剖分维护动态dp+二分
Description 小A走到一个山脚下,准备给自己造一个小屋.这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到山顶放了格水.于是小A面前出现了一个瀑布.作为平民的小A只好老实巴交地爬 ...
- 【BZOJ5210】最大连通子块和 树剖线段树+动态DP
[BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...
- bzoj5210最大连通子块和 (动态dp+卡常好题)
卡了一晚上,经历了被卡空间,被卡T,被卡数组等一堆惨惨的事情之后,终于在各位大爹的帮助下过了这个题qwqqq (全网都没有用矩阵转移的动态dp,让我很慌张) 首先,我们先考虑一个比较基础的\(dp\) ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- BZOJ4538:[HNOI2016]网络(树链剖分,堆)
Description 一个简单的网络系统可以被描述成一棵无根树.每个节点为一个服务器.连接服务器与服务器的数据线则看做 一条树边.两个服务器进行数据的交互时,数据会经过连接这两个服务器的路径上的所有 ...
- [树链剖分]BZOJ3589动态树
题目描述 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件 事件0: 这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子. 事件1: 小明希望你求出几条树枝上 ...
- bzoj5210 最大连通子块和 动态 DP + 堆
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5210 题解 令 \(dp[x][0]\) 表示以 \(x\) 为根的子树中的包含 \(x\) ...
随机推荐
- elasticsearch简单操作(二)
让我们建立一个员工目录,假设我们刚好在Megacorp工作,这时人力资源部门出于某种目的需要让我们创建一个员工目录,这个目录用于促进人文关怀和用于实时协同工作,所以它有以下不同的需求:1.数据能够包含 ...
- python四:函数练习--小白博客
为什么要有函数?函数式编程定义一次,多出调用函数在一定程度上可以理解为变量函数的内存地址加上()就是调用函数本身也可以当做参数去传参 不用函数:组织结构不清晰代码的重复性 def test():#te ...
- Jq相关常用操作
1.select下拉列表操作 $(".kstitle").live('change', function () { var workType = $(this).val(); // ...
- 使用faker去构造一个User-Agent
faker可以仿造各种各样的信息,可以使用faker去构造一个User-Agent from faker import Factory f = Factory.create() 'User-Agent ...
- PS调出甜美艺术外景女生照片
前期思路:拍摄时间大概在下午三四点左右,IOS100 f/1.8 .其实夏天最好的拍摄时间在傍晚五点这样,曝光太强片子会泛白,这张原片首先构图不是很好看,所以我要给它二次构图裁剪一下.下面是裁剪好后的 ...
- 09-babel
这个是解析我们es6的代码的,为什么要用它呢,因为对于一些ie浏览器,甚至FF浏览器,低版本的还不能识别我们的es6代码,那么vue里面好多还让我们去写es6的代码,这个时候我们就可以用babel这个 ...
- centos安装bundle文件
centos安装VMware-Workstation-Full-*.bundle那点事 | 鳗鱼是条狗https://kinggoo.com/centos-vmware.htm Linux 下 VMW ...
- 设置永久环境变量linux
========================================================================== http://www.cnblogs.com/Bi ...
- js 正则进阶regexp
一.匹配中文,英文字母和数字及_: const reg = /^[\u4e00-\u9fa5\w]+$/; const str1 = 'shangyy'; const str2 = '尚悦悦ww123 ...
- C调用C++, C++调用C方法
1. C 调用 C++封装好后的函数: -> 在C++中有一个函数 int main_cpp(): -> 首先构建头文件, #ifndef CPP_FILE_H #define CPP ...