https://www.luogu.org/problemnew/show/P4719

大概就是一条链一条链的处理(“链”在这里指重链),对于每一条链,对于其上每一个点,先算出它自身和所有轻儿子的贡献,当做这一步中这个点的“权值”,然后就变成序列上dp,直接用线段树维护

线段树版本O(n*log^2)

 #include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
struct E
{
int to,nxt;
}e[];
int f1[],ne;
struct P1
{
ll d[][];//左侧不选/选,右侧不选/选
};
struct P2
{
ll d[];//自身不选/选
};
ll a[];
int sz[],hson[],ff[];
int b[],pl[];
int n,m;
inline ll max1(ll a,ll b)
{
return a>b?a:b;
}
const ll inf1=-0x3f3f3f3f3f3f3f3f;
#define max max1
#define G(x) max1((x),inf1)
inline void merge(P1 &c,const P1 &a,const P1 &b)
{
c.d[][]=G(max(a.d[][]+max(b.d[][],b.d[][]),
a.d[][]+b.d[][]));
c.d[][]=G(max(a.d[][]+max(b.d[][],b.d[][]),
a.d[][]+b.d[][]));
c.d[][]=G(max(a.d[][]+max(b.d[][],b.d[][]),
a.d[][]+b.d[][]));
c.d[][]=G(max(a.d[][]+max(b.d[][],b.d[][]),
a.d[][]+b.d[][]));
}
inline void initnode(P1 &c,const P2 &a)
{
c.d[][]=a.d[];c.d[][]=a.d[];
c.d[][]=c.d[][]=inf1;
}
namespace S
{
#define lc (num<<1)
#define rc (num<<1|1)
P1 d[];
inline void upd(int num){merge(d[num],d[lc],d[rc]);}
P1 x;int L;
void _setx(int l,int r,int num)
{
if(l==r)
{
d[num]=x;
return;
}
int mid=(l+r)>>;
if(L<=mid) _setx(l,mid,lc);
else _setx(mid+,r,rc);
upd(num);
}
P1 getx(int L,int R,int l,int r,int num)
{
if(L<=l&&r<=R) return d[num];
int mid=(l+r)>>;
if(L<=mid&&mid<R)
{
P1 x;
merge(x,getx(L,R,l,mid,lc),getx(L,R,mid+,r,rc));
return x;
}
else if(L<=mid)
return getx(L,R,l,mid,lc);
else if(mid<R)
return getx(L,R,mid+,r,rc);
else
exit(-);
}
}
void dfs1(int u,int fa)
{
sz[u]=;
for(int v,k=f1[u];k;k=e[k].nxt)
if(e[k].to!=fa)
{
v=e[k].to;
ff[v]=u;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[hson[u]]) hson[u]=v;
}
}
P2 d1[];//d1[i]维护i节点及其轻儿子的贡献
P2 d2[];//d2[i]维护i节点(是重链顶)所在重链的dp值
int tp[],dwn[];//链顶,链底
void dfs2(int u,int fa)
{
d1[u].d[]=;d1[u].d[]=a[u];
b[++b[]]=u;pl[u]=b[];
tp[u]=(u==hson[fa])?tp[fa]:u;
if(hson[u]) dfs2(hson[u],u);
dwn[u]=hson[u]?dwn[hson[u]]:u;
int v,k;
for(k=f1[u];k;k=e[k].nxt)
if(e[k].to!=fa&&e[k].to!=hson[u])
{
v=e[k].to;
dfs2(v,u);
d1[u].d[]+=max(d2[v].d[],d2[v].d[]);
d1[u].d[]+=d2[v].d[];
}
initnode(S::x,d1[u]);S::L=pl[u];S::_setx(,n,);
if(u==tp[u])
{
P1 t=S::getx(pl[u],pl[dwn[u]],,n,);
d2[u].d[]=max(t.d[][],t.d[][]);
d2[u].d[]=max(t.d[][],t.d[][]);
}
}
int main()
{
int i,x,y;ll z;P1 t;
scanf("%d%d",&n,&m);
for(i=;i<=n;++i) scanf("%lld",a+i);
for(i=;i<n;++i)
{
scanf("%d%d",&x,&y);
e[++ne].to=y;e[ne].nxt=f1[x];f1[x]=ne;
e[++ne].to=x;e[ne].nxt=f1[y];f1[y]=ne;
}
dfs1(,);
dfs2(,);
while(m--)
{
scanf("%d%lld",&x,&z);
d1[x].d[]-=a[x];a[x]=z;d1[x].d[]+=z;
while(x)
{
initnode(S::x,d1[x]);S::L=pl[x];S::_setx(,n,);
x=tp[x];y=ff[x];
t=S::getx(pl[x],pl[dwn[x]],,n,);
d1[y].d[]-=max(d2[x].d[],d2[x].d[]);
d1[y].d[]-=d2[x].d[];
d2[x].d[]=max(t.d[][],t.d[][]);
d2[x].d[]=max(t.d[][],t.d[][]);
d1[y].d[]+=max(d2[x].d[],d2[x].d[]);
d1[y].d[]+=d2[x].d[];
x=y;
}
//printf("%lld %lld\n",d2[1].d[0],d2[1].d[1]);
printf("%lld\n",max(d2[].d[],d2[].d[]));
}
return ;
}

bst版本O(n*log)

待写

洛谷P4719 【模板】动态dp的更多相关文章

  1. 【洛谷P4719】动态dp 动态dp模板

    题目大意:给你一颗$n$个点的树,点有点权,有$m$次操作,每次操作给定$x$,$y$,表示修改点$x$的权值为$y$. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 数据范围:$n,m≤ ...

  2. 【洛谷4719】 动态dp(树链剖分,dp,矩阵乘法)

    前言 其实我只是为了过掉模板而写的ddp,实际应用被吊着锤 Solution 并不想写详细的过程 一句话过程:将子树中轻儿子的贡献挂到这个点上面来 详细版:(引用yyb) 总结一下的话,大致的过程是这 ...

  3. 洛谷P3373 [模板]线段树 2(区间增减.乘 区间求和)

    To 洛谷.3373 [模板]线段树2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.将某区间每一个数乘上x 3.求出某区间每一个数的和 输入输出格式 输入格 ...

  4. 洛谷P4719 【模板】"动态 DP"&动态树分治

    [模板]"动态 DP"&动态树分治 第一道动态\(DP\)的题,只会用树剖来做,全局平衡二叉树什么的就以后再学吧 所谓动态\(DP\),就是在原本的\(DP\)求解的问题上 ...

  5. 洛谷P4719 【模板】动态dp(ddp LCT)

    题意 题目链接 Sol 动态dp板子题.有些细节还没搞懂,待我研究明白后再补题解... #include<bits/stdc++.h> #define LL long long using ...

  6. 洛谷 P4719 【模板】动态dp【动态dp】

    是动态dp的板子 大致思想就是用g[u]来表示不包含重链转移的dp值,然后用线段树维护重链,这样线段树的根就相当于这条重链的top的真实dp值 每次修改的时候,修改x点会影响到x到根的真实dp值,但是 ...

  7. 洛谷P4719 动态dp

    动态DP其实挺简单一个东西. 把DP值的定义改成去掉重儿子之后的DP值. 重链上的答案就用线段树/lct维护,维护子段/矩阵都可以.其实本质上差不多... 修改的时候在log个线段树上修改.轻儿子所在 ...

  8. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  9. 洛谷P3928 Sequence2(dp,线段树)

    题目链接: 洛谷 题目大意在描述底下有.此处不赘述. 明显是个类似于LIS的dp. 令 $dp[i][j]$ 表示: $j=1$ 时表示已经处理了 $i$ 个数,上一个选的数来自序列 $A[0]$ 的 ...

  10. 洛谷P2224 [HNOI2001] 产品加工 [DP补完计划,背包]

    题目传送门 产品加工 题目描述 某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时 ...

随机推荐

  1. 重新拾取:ASP.NET Core WebApi 使用Swagger支持授权认证

    园子里已经有很多.NET Core 集成Swagger的文章,但对于使用授权的介绍蛮少的. public static class SwaggerServiceExtensions { public ...

  2. listen 55

    There are also green card qualifiers for some non-citizens who invest in America, and for refugees.难 ...

  3. ASCII UNICODE UTF "口水文"

    最近接了一个单是需要把非 UTF-8 (No BOM)编码的文件转换成 UTF-8 (No BOM),若此文件是 UTF-8 但带有 BOM ,需要转换成不带 BOM 的.于是开启了一天的阅读.首先花 ...

  4. rust borrow and move

    extern crate core; #[deriving(Show)] struct Foo { f : Box<int> } fn main(){ let mut a = Foo {f ...

  5. 文章预告的自我挖坑系列——D3.js 系列之星光闪烁

    D3.js 是个神奇的工具,下面收集了一些与星星相关的可视化的例子,静待慢慢的把坑填上 雷达图http://bl.ocks.org/kevinschaul/8213691      星空 二维(一)h ...

  6. 网络编程学习笔记-浅析socket

    一.问题的引入——socket的引入是为了解决不同计算机间进程间通信的问题 .socket与进程的关系 ).socket与进程间的关系:socket 用来让一个进程和其他的进程互通信息(IPC),而S ...

  7. sed 中带变量的情况

    #teststr="IBM" #sed -n '/' "$teststr" '/=' testfile.txt 在sed中使用变量 通常,我们使用sed进行变量 ...

  8. P1955 [NOI2015]程序自动分析[离散化+并查集]

    大水题一道,不明白为什么你谷评了个蓝.一看就是离散化,先去满足相等的条件,相等即为两点联通,或者说在同一个集合内.再看不相等,只有两元素在同一集合才不满足.裸的disjoint-set直接上,常数巨大 ...

  9. BZOJ2028:[SHOI2009]会场预约(平衡树版)

    浅谈\(splay\):https://www.cnblogs.com/AKMer/p/9979592.html 浅谈\(fhq\)_\(treap\):https://www.cnblogs.com ...

  10. CF 504 E —— Misha and LCP on Tree —— 树剖+后缀数组

    题目:http://codeforces.com/contest/504/problem/E 快速查询LCP,可以用后缀数组,但树上的字符串不是一个序列: 所以考虑转化成序列—— dfs 序! 普通的 ...