【洛谷P4315】月下“毛景树”(树链剖分)
生活随笔
收集整理的這篇文章主要介紹了
【洛谷P4315】月下“毛景树”(树链剖分)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
這是一道毒瘤題。
首先題目中給的是邊權而不是點權,但是我們把邊權移到點上就行了
但是要注意,之后我們修改u,v兩點之間的路徑時,就不要修改他們的lca,以及當要修改單邊的時候,把邊的編號*2(因為是雙向邊),然后挑深度大的那個點來修改
重點是區間覆蓋tag和區間加tag。首先注意,進行區間覆蓋時,一定要清零區間加tag。然后其次,pushdown的時候一定要先覆蓋再加
#include<bits/stdc++.h> #define INF 0x3f3f3f3f #define N 100005 using namespace std; template<class T> inline void read(T &x) {x=0;static char ch=getchar();while(ch<'0'||ch>'9') ch=getchar();while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } int n,first[2*N],tot; struct Edge{int from,to,next,val;}edge[2*N]; inline void addedge(int x,int y,int z) {tot++; edge[tot].from=x; edge[tot].to=y; edge[tot].next=first[x]; edge[tot].val=z; first[x]=tot; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ int depth[N],size[N],maxson[N],father[N],val[N]; void dfs1(int now,int fa) {depth[now]=depth[fa]+1;father[now]=fa;size[now]=1;for(int u=first[now];u;u=edge[u].next){int vis=edge[u].to;if(vis==fa) continue;dfs1(vis,now);val[vis]=edge[u].val;size[now]+=size[vis];if(size[vis]>size[maxson[now]]) maxson[now]=vis;} } int top[N],id[N],wnew[N],sign; void dfs2(int now,int topf) {top[now]=topf;id[now]=++sign;wnew[sign]=val[now];if(maxson[now]) dfs2(maxson[now],topf);for(int u=first[now];u;u=edge[u].next){int vis=edge[u].to;if(vis==maxson[now]||vis==father[now]) continue;dfs2(vis,vis);} } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ struct Tree{int l,r,maxv,cover,lazy_add;}tree[4*N]; inline void pushup(int now){ tree[now].maxv=max(tree[2*now].maxv,tree[2*now+1].maxv); } inline void pushdown(int now) {if(tree[now].cover!=-1){tree[2*now].lazy_add=tree[2*now+1].lazy_add=0;tree[2*now].cover=tree[2*now].maxv=tree[now].cover;tree[2*now+1].cover=tree[2*now+1].maxv=tree[now].cover;tree[now].cover=-1;}tree[2*now].maxv+=tree[now].lazy_add;tree[2*now+1].maxv+=tree[now].lazy_add;tree[2*now].lazy_add+=tree[now].lazy_add;tree[2*now+1].lazy_add+=tree[now].lazy_add; tree[now].lazy_add=0; } void build(int now,int l,int r) {tree[now].l=l,tree[now].r=r,tree[now].cover=-1,tree[now].lazy_add=0;if(l==r) {tree[now].maxv=wnew[l];return;}int m=(l+r)>>1;build(2*now,l,m);build(2*now+1,m+1,r);pushup(now); } inline void add(int now,int l,int r,int w) {if(l<=tree[now].l&&tree[now].r<=r){tree[now].lazy_add+=w;tree[now].maxv+=w;return;}pushdown(now);int m=(tree[now].l+tree[now].r)>>1;if(l<=m) add(2*now,l,r,w);if(r>m) add(2*now+1,l,r,w);pushup(now); } inline void cover(int now,int l,int r,int w) {if(l<=tree[now].l&&tree[now].r<=r){tree[now].cover=w;tree[now].maxv=w;tree[now].lazy_add=0;return;}pushdown(now);int m=(tree[now].l+tree[now].r)>>1;if(l<=m) cover(2*now,l,r,w);if(r>m) cover(2*now+1,l,r,w);pushup(now); } inline int query(int now,int l,int r) {if(l<=tree[now].l&&tree[now].r<=r) return tree[now].maxv;pushdown(now);int m=(tree[now].l+tree[now].r)>>1,res=-INF;if(l<=m) res=max(res,query(2*now,l,r));if(r>m) res=max(res,query(2*now+1,l,r));return res; } inline void Tcover(int x,int y,int z) {while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);cover(1,id[top[x]],id[x],z);x=father[top[x]];}if(depth[x]>depth[y]) swap(x,y);cover(1,id[x]+1,id[y],z); //lca不能被更新! } inline void Tadd(int x,int y,int z) {while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);add(1,id[top[x]],id[x],z);x=father[top[x]];}if(depth[x]>depth[y]) swap(x,y);add(1,id[x]+1,id[y],z); } inline int Qmax(int x,int y) {int ans=0;while(top[x]!=top[y]){if(depth[top[x]]<depth[top[y]]) swap(x,y);ans=max(ans,query(1,id[top[x]],id[x]));x=father[top[x]];}if(depth[x]>depth[y]) swap(x,y);return max(ans,query(1,id[x]+1,id[y])); } int main() {read(n);for(int i=1,u,v,w;i<=n-1;i++){read(u),read(v),read(w);addedge(u,v,w); addedge(v,u,w);}dfs1(1,0); dfs2(1,1); build(1,1,n);string s;while(cin>>s){int u,v,w; if(s=="Stop") return 0;if(s=="Max"){read(u),read(v);cout<<Qmax(u,v)<<'\n';}if(s=="Change") //單點修改 {read(u),read(v);u*=2; //加的雙向邊 u=depth[edge[u].from]>depth[edge[u].to]?edge[u].from:edge[u].to;cover(1,id[u],id[u],v);}if(s=="Add") //區間加{read(u),read(v),read(w);Tadd(u,v,w);} if(s=="Cover"){read(u),read(v),read(w);Tcover(u,v,w);}}return 0; }轉載于:https://www.cnblogs.com/Patrickpwq/articles/9865938.html
總結
以上是生活随笔為你收集整理的【洛谷P4315】月下“毛景树”(树链剖分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Linux 线程】常用线程函数复习《三
- 下一篇: 【线性代数】2-5:逆(Inverse)