博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
F - 八苦を滅した尼公 POJ - 2763 线段树LCA
阅读量:4681 次
发布时间:2019-06-09

本文共 2602 字,大约阅读时间需要 8 分钟。

//#include
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;#define ll long long#define pb push_backconst int maxn=1e6+7;const int inf=0x3f3f3f3f;struct EDGE{ int u,v,val,next;}G[maxn<<1];int tot;int head[maxn];void init(){ memset(head,-1,sizeof head);tot=0;}void addedge(int u,int v,int w){ tot++;G[tot]={u,v,w,head[u]};head[u]=tot;}int vs[maxn<<1];int in[maxn],out[maxn];int tim; int dep[maxn<<1];int id[maxn];int pre[maxn];void dfs(int u,int fa,int d){ pre[u]=fa; id[u]=++tim;vs[tim]=u;dep[tim]=d; in[u]=tim;out[u]=tim; for(int i=head[u];~i;i=G[i].next){ EDGE e=G[i]; if(e.v==fa)continue; dfs(e.v,u,d+e.val); vs[++tim]=u;dep[tim]=d;out[u]=tim; }}struct node{ int fa; //区间内公共祖先 int mindep; int add; //lazy}ST[maxn<<2];void pushdown(int rt){ if(ST[rt].add){ ST[rt<<1].mindep+=ST[rt].add;ST[rt<<1|1].mindep+=ST[rt].add; ST[rt<<1].add+=ST[rt].add;ST[rt<<1|1].add+=ST[rt].add; ST[rt].add=0; }}void pushup(int rt){ if(ST[rt<<1].mindep<=ST[rt<<1|1].mindep){ ST[rt].mindep=ST[rt<<1].mindep; ST[rt].fa=ST[rt<<1].fa; }else{ ST[rt].mindep=ST[rt<<1|1].mindep; ST[rt].fa=ST[rt<<1|1].fa; }}void build(int l,int r,int rt){ if(l==r){ ST[rt].mindep=dep[l]; ST[rt].fa=vs[l]; ST[rt].add=0; return; } ST[rt].add=0; int m=l+r>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt);}void update(int a,int b,int c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].mindep+=c; ST[rt].add+=c; return; } pushdown(rt); int m=l+r>>1; if(a<=m)update(a,b,c,l,m,rt<<1); if(b>m)update(a,b,c,m+1,r,rt<<1|1); pushup(rt);}node query(int a,int b,int l,int r,int rt){ //查询a-b内的祖先 //cout<
<<" "<<<" "<
<<" "<
<
=r){ return ST[rt]; } pushdown(rt); int m=l+r>>1; node n2={0,inf,0},n1={0,inf,0}; if(a<=m)n1=query(a,b,l,m,rt<<1); if(b> m)n2=query(a,b,m+1,r,rt<<1|1); if(n1.mindep
v)swap(u,v); addedge(u,v,w); addedge(v,u,w); } int now=s; tim=0; dep[s]=0; dfs(s,s,0); build(1,tim,1); for(int i=1;i<=q;i++){ int kind;int a,b; scanf("%d",&kind); if(kind){ //改边 scanf("%d%d",&a,&b); a=2*a-1; int flag=0; if(pre[G[a].v]==G[a].u){flag=1;} else a++; EDGE e=G[a]; int plus=b-e.val; update(in[e.v],out[e.v],plus,1,tim,1); if(flag){ G[a].val=b; G[a+1].val=b; }else{ G[a].val=b; G[a-1].val=b; } //for(int i=1;i<=tim;i++){ // cout<
<<"ss"<

核心就是vs序列存下的in[u],out[u]的中间段只有u的子树

做法肯定不是最优的,因为检查每个节点的深度我都用到了线段树查询,慢了3倍
换上树状数组肯定能更快,但我懒得学。。
双向边的编号修改难死我了。。。还好想出办法解决了
(其实是别人的代码我看不懂

转载于:https://www.cnblogs.com/Drenight/p/8611301.html

你可能感兴趣的文章
C++Primer笔记-----day01
查看>>
MSSQL 各个发行版本版本号以及Compact 版本号(更新)
查看>>
tslint.json的配置项说明
查看>>
iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 代码分层
查看>>
C# 优化程序的四十七种方法
查看>>
Manacher算法——最长回文子串(O(n))
查看>>
web开发如何使用高德地图API(二)结合输入提示和POI搜索插件
查看>>
hdu 4349 Xiao Ming's Hope lucas
查看>>
Asp.net下载功能的解决方案代码
查看>>
linux积累
查看>>
预处理-03-文件包含、条件编译、小结
查看>>
Codeforces Round #417 (Div. 2) E. Sagheer and Apple Tree(树上Nim)
查看>>
Wannafly挑战赛1 C MMSet2
查看>>
sgu 197 Nice Patterns Strike Back
查看>>
Java的初步认识
查看>>
笔记:虚拟机类加载机制
查看>>
combobox中动态载入tree数据
查看>>
【课程12】循环嵌套和算法
查看>>
设计模式——外观模式
查看>>
mongodb 脚本操作
查看>>