题意

给出 \(n\) 个点的树,每个时刻可能出现一条路径 \(A_i\) 或者之前出现的某条路径 \(A_i\) 消失,每条路径有一个权值,求出在每个时刻过后能够找到的权值最大的路径(指所有和该路径有交的路径 \(A\) 的权值和) \(B\) 的权值是多少。

\(n\leq 10^5\)

分析

结论:两条树上路径有交,则一定有一条路径经过另一条路径的 \(lca\).

  • 根据上面的性质我们考虑用树形dp的方式求解。

  • 将一条路径的权值在每个点 \(x\) 关系分成两种:

    • \(a\) :路径的 \(lca\) 是 \(x\) ;
    • \(b\) :路径的 \(lca\) 是 \(x\) 的祖先;
  • 假设现在已经选定了一条路径 \(B\),那么该路径的权值就是途径所有点的 \(a\) 和 \(lca\) 的 \(b\) 之和 .

  • 考虑动态dp,因为树剖之后答案一定可以写成一段轻链+一段重链+一段轻链的形式。

  • 然后全局再用一个可删堆维护每条重链的答案即可。

  • 总时间复杂度为 \(O(nlog^2n)\)。

注意可删堆取次大值时要两次检查堆顶是否要被删除

代码

#include<bits/stdc++.h>
using namespace std;
#define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].lst,v=e[i].to)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define pb push_back
typedef long long LL;
inline int gi(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
return x*f;
}
template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
const int N=1e5 + 7,Nd=N<<2;
int n,m,edc;
int head[N],x[N],y[N],w[N];
struct edge{
int lst,to;
edge(){}edge(int lst,int to):lst(lst),to(to){}
}e[N*2];
void Add(int a,int b){
e[++edc]=edge(head[a],b),head[a]=edc;
e[++edc]=edge(head[b],a),head[b]=edc;
}
// slpf
int son[N],zson[N],fa[N],dep[N],in[N],top[N],rev[N],down[N],tim;
void dfs1(int u){
son[u]=1;
go(u)if(v^fa[u]){
fa[v]=u,dep[v]=dep[u]+1,dfs1(v);
son[u]+=son[v];
if(son[v]>son[zson[u]]) zson[u]=v;
}
}
void dfs2(int u,int from){
top[u]=from,in[u]=++tim,rev[tim]=u,down[u]=u;
if(zson[u]) dfs2(zson[u],from),down[u]=down[zson[u]];
go(u)if(v^fa[u]&&v^zson[u]) dfs2(v,v);
}
int Lca(int x,int y){
for(;top[x]^top[y];y=fa[top[y]])
if(dep[top[x]]>dep[top[y]]) swap(x,y);
return dep[x]<dep[y]?x:y;
}
//sgt
#define Ls o<<1
#define Rs o<<1|1
struct data{
LL l,r,s,mx;
data(){}
data operator +(const data &rhs)const{
data res;
res.l=max(l,s+rhs.l);
res.r=max(rhs.r,rhs.s+r);
res.s=s+rhs.s;
res.mx=max(max(mx,rhs.mx),r+rhs.l);
return res;
}
}t[N<<2];
char s[10];
LL addv[Nd],g[Nd],se[Nd];
void st1(int o,LL v){
t[o].r+=v,t[o].mx+=v;
addv[o]+=v;
}
void pushup(int o){
t[o]=t[Ls]+t[Rs];
}
void pushdown(int o){
if(!addv[o]) return;
st1(Ls,addv[o]);
st1(Rs,addv[o]);
addv[o]=0;
}
void ma(int p,int l,int r,int o,int opt,LL v){
if(l==r){
if(!opt){
t[o].l+=v,t[o].r+=v,t[o].s+=v,t[o].mx+=v;
}else if(opt==1){
LL x=v-g[o];g[o]=v;
t[o].l+=x,t[o].r+=x,t[o].mx+=x;
}else{
LL x=v-se[o];se[o]=v;
t[o].mx+=x;
}
return;
}
pushdown(o);int mid=l+r>>1;
if(p<=mid) ma(p,l,mid,Ls,opt,v);
else ma(p,mid+1,r,Rs,opt,v);
pushup(o);
}
void mb(int L,int R,int l,int r,int o,LL v){
if(L>R) return;
if(L<=l&&r<=R){
st1(o,v);
return;
}
pushdown(o);int mid=l+r>>1;
if(L<=mid) mb(L,R,l,mid,Ls,v);
if(R>mid) mb(L,R,mid+1,r,Rs,v);
pushup(o);
}
data query(int L,int R,int l,int r,int o){
if(L<=l&&r<=R) return t[o];
pushdown(o);int mid=l+r>>1;
if(R<=mid) return query(L,R,l,mid,Ls);
if(L>mid) return query(L,R,mid+1,r,Rs);
return query(L,R,l,mid,Ls)+query(L,R,mid+1,r,Rs);
}
struct Heap{
priority_queue<LL>A,B;
void push(LL x){A.push(x);}
void pop(LL x){B.push(x);}
LL top(){
while(!B.empty()&&A.top()==B.top()) A.pop(),B.pop();
return A.empty()?0:A.top();
}
LL se(){
while(!B.empty()&&A.top()==B.top()) A.pop(),B.pop();
if(A.empty()) return -1;
LL x=A.top();A.pop();
while(!B.empty()&&A.top()==B.top()) A.pop(),B.pop();
if(B.empty()) {A.push(x);return -1;}
LL y=A.top();A.push(x);
return y;
}
}h[N],ans;
LL tans[N];
void upd(int u,int lca,LL v){
int x=u;
for(;u;u=fa[top[u]]){
int gg=fa[top[u]]; data res=query(in[top[u]],in[down[u]],1,n,1);
h[gg].pop(res.l);
if(tans[top[u]]) ans.pop(tans[top[u]]); if(u==x&&!lca) ma(in[u],1,n,1,0,v);
else{
if(lca) mb(max(in[top[u]],in[lca]+1),in[u],1,n,1,v);
ma(in[u],1,n,1,1,h[u].top());
} if(h[u].se()!=-1) ma(in[u],1,n,1,2,h[u].se());
res=query(in[top[u]],in[down[u]],1,n,1);
h[gg].push(res.l);
ans.push(tans[top[u]]=res.mx);
}
}
void pre(int u){
go(u)if(v^fa[u]) pre(v);
h[fa[top[u]]].push(0),ans.push(0);
}
int main(){
n=gi(),m=gi();
rep(i,1,n-1) Add(gi(),gi());
dep[1]=1,dfs1(1),dfs2(1,1);
pre(1);
rep(i,1,m){
scanf("%s",s);
if(s[0]=='+'){
x[i]=gi(),y[i]=gi(),w[i]=gi();
int lca=Lca(x[i],y[i]);
upd(lca,0,w[i]);
upd(x[i],lca,w[i]);
upd(y[i],lca,w[i]);
}else{
int t=gi(),lca=Lca(x[t],y[t]);
upd(lca,0,-w[t]);
upd(x[t],lca,-w[t]);
upd(y[t],lca,-w[t]);
}
printf("%lld\n",ans.top());
}
return 0;
}

[UOJ#268]. 【清华集训2016】数据交互[动态dp+可删堆维护最长链]的更多相关文章

  1. BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...

  2. UOJ268 [清华集训2016] 数据交互 【动态DP】【堆】【树链剖分】【线段树】

    题目分析: 不难发现可以用动态DP做. 题目相当于是要我求一条路径,所有与路径有交的链的代价加入进去,要求代价最大. 我们把链的代价分成两个部分:一部分将代价加入$LCA$之中,用$g$数组保存:另一 ...

  3. BZOJ4732. [清华集训2016]数据交互(树链剖分+线段树+multiset)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=4732 题解 首先,一个比较显然的结论是:对于一棵有根树上的两条链 \((x_1, y_1 ...

  4. [UOJ#274][清华集训2016]温暖会指引我们前行

    [UOJ#274][清华集训2016]温暖会指引我们前行 试题描述 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一 ...

  5. Uoj #274. 【清华集训2016】温暖会指引我们前行 LCT维护边权_动态最小生成树

    Code: 行#include<bits/stdc++.h> #define ll long long #define maxn 1000000 #define inf 100000000 ...

  6. [UOJ#276][清华集训2016]汽水[分数规划+点分治]

    题意 给定一棵 \(n\) 个点的树,给定 \(k\) ,求 \(|\frac{\sum w(路径长度)}{t(路径边数)}-k|\)的最小值. \(n\leq 5\times 10^5,k\leq ...

  7. [UOJ#276]【清华集训2016】汽水

    [UOJ#276][清华集训2016]汽水 试题描述 牛牛来到了一个盛产汽水的国度旅行. 这个国度的地图上有 \(n\) 个城市,这些城市之间用 \(n−1\) 条道路连接,任意两个城市之间,都存在一 ...

  8. UOJ 275. 【清华集训2016】组合数问题

    UOJ 275. [清华集训2016]组合数问题 组合数 $C_n^m $表示的是从 \(n\) 个物品中选出 \(m\) 个物品的方案数.举个例子,从$ (1,2,3)(1,2,3)$ 三个物品中选 ...

  9. UOJ #269. 【清华集训2016】如何优雅地求和

    UOJ #269. [清华集训2016]如何优雅地求和 题目链接 给定一个\(m\)次多项式\(f(x)\)的\(m+1\)个点值:\(f(0)\)到\(f(m)\). 然后求: \[ Q(f,n,x ...

随机推荐

  1. windows 服务器远程桌面 你的凭据不工作

    一.问题描述   通过windows 远程桌面连接服务器时,输入正确的用户名和密码,点击连接按钮时,提示“你的凭据不工作”,但是其他个别电脑可以通过远程桌面远程到目标服务器.问题描述如下图所示: 二. ...

  2. oracle EBS rtf报表不能输出模板样式

    1.需要定义中文的数据定义 2.缺少文件 cd $ADMIN_SCRIPTS_HOME prefs.ora 3.查看文档  文档 ID 1059712.1 (1)请求模版显示不出来 解决:模版定义中模 ...

  3. Oracle EBS 物化视图

    怎么理解物化视图呢,先随意拿一个建物化视图的例子看一下. create materialized view EBS_ACCOUNTS_HIERARCHY_MV refresh complete on ...

  4. java8时间操作

    import java.time.*; import java.util.Date; /** * @Auther kejiefu * @Date 2018/5/17 0017 */ public cl ...

  5. 转:Sql Server中的表访问方式Table Scan, Index Scan, Index Seek

    0.参考文献 Table Scan, Index Scan, Index Seek SQL SERVER – Index Seek vs. Index Scan – Diffefence and Us ...

  6. abp框架里使用Redis

    首先引用 nuget Abp.RedisCache 在 appsettings.json加上Redis服务器配置 "RedisCache": { "ConnectionS ...

  7. Java多线程学习笔记之一线程基础

    1.进程与线程 1.1 进程:是正在运行中的程序的实例,一个运行中idea就是一个进程.进程有它自己的地址空间,一般情况下,包括文本区域(text region).数据区域(data region)和 ...

  8. Eclipse 中怎样自动格式化代码?

    首先 有一个 检查代码风格的工具叫checkstyle,具体怎么下载,请自行百度.. 当你在eclipse安装好 checkstyle后,对于使用google标准的人来说,选择一个项目,右键,点击ch ...

  9. react-native-storage 使用笔记 持续更新

    React-native-storage是在AsyncStorage之上封装的一个缓存操作插件库,刚开始接触这个也遇到了一些问题,在这里简单记录总结一下,碰到了就记下来,持续更新吧 1.安卓下stor ...

  10. css3自定义滚动条背景透明

    .editor{ overflow:hidden; height:640px; padding:0 45px; border: 0 none; outline: none; } .editor::-w ...