【清华集训2016】数据交互
【清华集训2016】数据交互
比较神的\(DDP\)。
首先对于给出的一条链我们分两部分统计:\(lca\)以及其他部分。
我们设两个变量\(w_i,g_i\)。一条路径的权值就是路径上所有点的\(w\)之和\(+g_{lca}\)。所以我们将修改\(w_{lca}\)的权值,修改其他点的\(g\)值。删除的时候就加一条相同的,权值相反的路径。
具体细节就有多了。
首先我们给每个点\(v\)开一个可删除堆表示\(v\)的虚子树中到\(v\)的最长链。再开一个全局的可删除堆记录每条链贡献的答案。我们发现,一条路径可以看成是重链上的\(u,v\)两点(其中\(u\)是\(lca\)),以及这两点分别向虚子树伸出去的一条最长链(可以为空)。它的权值为这条链的\(g\)之和再加上\(w_u\)。当\(u\)等于\(v\)的时候,我们需要找最长链和次长链。
我们发现这就是一个最大连续子段和。
对于线段树上的一个节点,我们记录:
\(mx\)表示答案。
\(lmx\)表示从最左边代表的节点(深度最小)开始的最长链。
\(rmx\)表示从最右边代表的节点(深度最大)开始的最长链。
还要记录\(sum\)表示区间内所有节点的\(w\)只和。
一条重链的链顶的最长链就是这条重链对应的\(lmx\)。
修改的时候暴力将\(lca\)以上\(log\)条重链原来对其父亲贡献的最长链删除掉。更新过后将新的最长链贡献上去。
更多细节就看代码吧:
#include<bits/stdc++.h>
#define ll long long
#define N 100005using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}int n,m;
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}int fa[N],dep[N];
int size[N],son[N];void dfs(int v) {size[v]=1;for(int i=h[v];i;i=s[i].next) {int to=s[i].to;if(to==fa[v]) continue ;dep[to]=dep[v]+1;fa[to]=v;dfs(to);if(size[son[v]]<size[to]) son[v]=to;size[v]+=size[to];}
}int dfn[N],bot[N],top[N],id;
int lst[N];
void dfs2(int v,int tp) {dfn[v]=++id;lst[id]=v;top[v]=tp;bot[v]=v;if(son[v]) {dfs2(son[v],tp);bot[v]=bot[son[v]];}for(int i=h[v];i;i=s[i].next) {int to=s[i].to;if(to==fa[v]||to==son[v]) continue ;dfs2(to,to);}
}struct tree {int l,r;ll lmx,rmx;ll mx,tag;ll sum;tree() {l=r=lmx=rmx=mx=tag=sum=0;}
}tr[N<<2];struct Heap {priority_queue<ll>add,del;void Pop() {while(del.size()&&add.top()==del.top()) {add.pop();del.pop();}}void Push(ll x) {Pop();add.push(x);}void Del(ll x) {del.push(x);}ll Top() {Pop();return add.top();}ll Sec() {ll x=Top();Del(x);ll y=Top();Push(x);return y;}
}Ans,F[N];tree operator +(const tree &a,const tree &b) {tree tem;tem.l=a.l,tem.r=b.r;tem.mx=max(a.rmx+b.lmx,max(a.mx,b.mx));tem.lmx=max(a.lmx,a.sum+b.lmx);tem.rmx=max(b.rmx,a.rmx+b.sum);tem.sum=a.sum+b.sum;return tem;
}// sum 单点
//tag 链
void Update(int v,int p) {int u=lst[p];ll fir=F[u].Top(),sec=F[u].Sec();tr[v].lmx=tr[v].sum+fir;tr[v].rmx=tr[v].tag+tr[v].sum+fir;tr[v].mx=tr[v].tag+tr[v].sum+fir+sec;
}void build(int v,int l,int r) {tr[v].l=l,tr[v].r=r;if(l==r) {Update(v,l);return ;}int mid=l+r>>1;build(v<<1,l,mid),build(v<<1|1,mid+1,r);tr[v]=tr[v<<1]+tr[v<<1|1];
}void Set(int v,ll f) {tr[v].mx+=f;tr[v].tag+=f;
// tr[v].lmx+=f;tr[v].rmx+=f;
}void down(int v) {if(tr[v].tag) {Set(v<<1,tr[v].tag),Set(v<<1|1,tr[v].tag);tr[v].tag=0;}
}void add_mx(int v,int l,int r,ll f) {//修改给出的整条链 if(tr[v].l>r||tr[v].r<l) return ;if(l<=tr[v].l&&tr[v].r<=r) {Set(v,f);return ;}down(v);add_mx(v<<1,l,r,f),add_mx(v<<1|1,l,r,f);tr[v]=tr[v<<1]+tr[v<<1|1];
}void add_sum(int v,int p,int f) {//修改lca if(tr[v].l>p||tr[v].r<p) return ;tr[v].sum+=f;if(tr[v].l==tr[v].r) {tr[v].lmx+=f;tr[v].rmx+=f;tr[v].mx+=f;return ;}down(v);add_sum(v<<1,p,f),add_sum(v<<1|1,p,f);tr[v]=tr[v<<1]+tr[v<<1|1];
}void update(int v,int p) {if(tr[v].l>p||tr[v].r<p) return ;if(tr[v].l==tr[v].r) {Update(v,p);return ;}down(v);update(v<<1,p),update(v<<1|1,p);tr[v]=tr[v<<1]+tr[v<<1|1];
}tree query(int v,int l,int r) {if(l<=tr[v].l&&tr[v].r<=r) return tr[v];down(v);int mid=tr[v].l+tr[v].r>>1;if(r<=mid) return query(v<<1,l,r);else if(l>mid) return query(v<<1|1,l,r);else return query(v<<1,l,r)+query(v<<1|1,l,r);
}int lca(int a,int b) {while(top[a]!=top[b]) {if(dep[top[a]]<dep[top[b]]) swap(a,b);a=fa[top[a]];}return dep[a]<dep[b]?a:b;
}void Modify_chain(int a,int b,int f) {while(top[a]!=top[b]) {if(dep[top[a]]<dep[top[b]]) swap(a,b);add_mx(1,dfn[top[a]],dfn[a],f);a=fa[top[a]];}if(dep[a]>dep[b]) swap(a,b);add_mx(1,dfn[a],dfn[b],f);
}void Del(int a,int b) {static tree tem;while(top[a]!=top[b]) {if(dep[top[a]]<dep[top[b]]) swap(a,b);tem=query(1,dfn[top[a]],dfn[bot[a]]);Ans.Del(tem.mx);a=fa[top[a]];}tem=query(1,dfn[top[a]],dfn[bot[a]]);Ans.Del(tem.mx);
}void ADD(int a,int b) {static tree tem;while(top[a]!=top[b]) {if(dep[top[a]]<dep[top[b]]) swap(a,b);tem=query(1,dfn[top[a]],dfn[bot[a]]);Ans.Push(tem.mx);a=fa[top[a]];}tem=query(1,dfn[top[a]],dfn[bot[a]]);Ans.Push(tem.mx);
}void Modify(int a,int b,int w) {int f=lca(a,b);tree tem;for(int i=top[f];i;i=top[fa[i]]) {tem=query(1,dfn[i],dfn[bot[i]]);if(fa[i]) F[fa[i]].Del(tem.lmx);if(i!=top[f]) {Ans.Del(tem.mx);}}Del(a,b);add_sum(1,dfn[f],w);Modify_chain(a,b,w);Modify_chain(f,f,-w);ADD(a,b);for(int i=top[f];i;i=top[fa[i]]) {tem=query(1,dfn[i],dfn[bot[i]]);if(fa[i]) {F[fa[i]].Push(tem.lmx);update(1,dfn[fa[i]]);}if(i!=top[f]) Ans.Push(tem.mx);}
}struct edge {int x,y,w;}e[N];
void out(int v) {int x=top[v];for(int i=dfn[x];;i++) {cout<<lst[i]<<" ";if(i==dfn[v]) return ;}
}int main() {n=Get(),m=Get();int a,b;for(int i=1;i<n;i++) {a=Get(),b=Get();add(a,b),add(b,a);}dfs(1);dfs2(1,1);for(int i=1;i<=n;i++) F[i].Push(0),F[i].Push(0);build(1,1,n);for(int i=1;i<=n;i++) if(i==top[i]) Ans.Push(0);char op;for(int i=1;i<=m;i++) {while(op=getchar(),op!='+'&&op!='-');if(op=='+') {e[i].x=Get(),e[i].y=Get(),e[i].w=Get();Modify(e[i].x,e[i].y,e[i].w);} else {int id=Get();Modify(e[id].x,e[id].y,-e[id].w);}cout<<Ans.Top()<<"\n";}return 0;
}
转载于:https://www.cnblogs.com/hchhch233/p/10566528.html
【清华集训2016】数据交互相关推荐
- BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- UOJ #268 BZOJ 4732 [清华集训2016]数据交互 (树链剖分、线段树)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...
- UOJ #274. 【清华集训2016】温暖会指引我们前行 [lct]
#274. [清华集训2016]温暖会指引我们前行 题意比较巧妙 裸lct维护最大生成树 #include <iostream> #include <cstdio> #incl ...
- [清华集训2016]石家庄的工人阶级队伍比较坚强——三进制FWT
题目链接: [清华集训2016]石家庄的工人阶级队伍比较坚强 题目大意:有$n=3^m$个人玩石头剪刀布,共$t$轮游戏,每轮每个人要和包括自己的所有人各进行$m$次石头剪刀布.每个人在$m$轮中的决 ...
- P6669 [清华集训2016] 组合数问题
P6669 [清华集训2016] 组合数问题 题意: 给你n,m,k,问有多少对(i,j)满足K∣CijK|C_{i}^{j}K∣Cij (Cij是k的倍数C_{i}^{j}是k的倍数Cij是k的 ...
- [清华集训2016]你的生命已如风中残烛——组合数学
题目链接: [清华集训2016]你的生命已如风中残烛 题目大意:共有$m+1$张牌,其中有$n$张特殊牌,每张特殊牌有一个权值$w_{i}$表示取到这张牌能获得$w_{i}$次再抽牌的机会,保证$\s ...
- uoj#268. 【清华集训2016】数据交互(动态dp+堆)
传送门 动态dp我好像还真没咋做过--通过一个上午的努力光荣的获得了所有AC的人里面的倒数rk3 首先有一个我一点也不觉得显然的定理,如果两条路径相交,那么一定有一条路径的\(LCA\)在另一条路径上 ...
- BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)
BZOJ UOJ 记\(val_i\)是每条边的边权,\(s\)是边权和,\(t\)是经过边数,\(k\)是给定的\(k\). 在点分治的时候二分答案\(x\),设\(|\frac st-k|=x\) ...
- UOJ#274. 【清华集训2016】温暖会指引我们前行
寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 "冻死宝宝了!" 这时 远处的天边出现了一位火焰之神 "我将赐予你们温暖和希望! ...
最新文章
- java object finalize_Java Object finalize() 方法
- 树莓派安装python2idle_树莓派开发日记2——Linux!python!GPIO!
- 基于现代神经网络通用人工智能架构设计
- 【原】移动web动画设计的一点心得——css3实现跑步
- 在Python Shell中输入print 'hello'总是报语法错误
- CALayer与UIView区别和联系【转】
- java 图像渲染_对具有大量图像的视图执行本机渲染性能
- androidpn的学习研究(三)androidpn-server服务端几个类说明
- python提前退出内层循环,python with提前退出遇到的坑与解决方案
- oracle 字符串等于,ORACLE in (字符串,字符串,字符串)
- 图(3)——邻接链表法
- IEEE期刊最新的影响因子
- 【调剂】长江大学张菲菲教授招收硕士生
- 教授专栏14 | 陈泰元: 提升公司治理之路--高管薪酬追回条款
- Python学习必看书籍_带你高效学习
- Redis过期策略---实现原理
- 卸载Autodesk系列之后电脑屏幕灰白怎么解决
- 机器学习之随机森林填补缺失值和众数填补缺失值
- linux远程文件拷贝方式,linux远程拷贝文件
- 矮油~ 二叉树的深度优先遍历与广度优先遍历 [ C++ 实现 ]
热门文章
- [python数据分析] 简述幂率定律及绘制Power-law函数
- linux kvm百度云,如何在 Ubuntu Linux 上使用 KVM 云镜像
- 科学家解码脑信号以控制机器人假肢
- 通过细胞自动机,AI在「我的世界」学会了盖房子
- 数学好=编程能力强?MIT新发现:二者激活大脑区域并不同
- RTX 3090 AI性能实测:FP32训练速度提升50%,张量核心缩水
- 专访阿里达摩院聂再清:不能让每个人无差别享受AI,是程序员的耻辱
- 一路撑起支付宝的OceanBase数据库,背后究竟有哪些杀手锏?| 云·创课程报名
- 被乐高AI“照妖镜”一照,发现你的本体原来是人偶
- 禾多推出高精度定位和自动驾驶验证平台!倪凯:助力行业量产,定位中国向导...