洛谷1505 旅遊(樹鏈剖分)
阿新 • • 發佈:2018-12-17
QAQ
【題目分析】
一道裸的剖分被一個極度sb的錯誤卡了兩天。。。。。。
題意很明顯,維護5個操作:單點修改,區間取相反數,區間求和,區間求最大值,區間求最小值。
因為求一條路徑,考慮樹鏈剖分維護(注意dfs序時優先dfs重兒子!!!這樣線上段樹上的編號才連續!!!)
考慮第一個操作,對於一條路徑,如果修改了他的權值,那麼只會對深度較淺的一個點向下走、深度較深的向上走會產生影響,所以單點修改較深點權值。(見程式碼update1操作)
考慮第二個操作,就是區間交換最大值最小值、區間和最大值最小值取反即可(見程式碼push_now操作)
考慮第三、四、五個操作,直接在樹剖的時候統計答案即可。
【程式碼~】
#include<bits/stdc++.h> using namespace std; const int MAXN=1e5+10; const int MAXM=1e6+10; const int INF=0x3f3f3f3f; int n,m,cnt=1,tot; int head[MAXN],fa[MAXN],top[MAXN],depth[MAXN],siz[MAXN],son[MAXN]; int a[MAXN],dfn[MAXN],ys[MAXN]; struct Edge{ int to,nxt,w; }edge[MAXM]; struct node{ int l,r; int sum,maxx,minn; int tag; }tr[MAXN<<2]; void push_up(int root) { tr[root].sum=tr[root<<1].sum+tr[root<<1|1].sum; tr[root].maxx=max(tr[root<<1].maxx,tr[root<<1|1].maxx); tr[root].minn=min(tr[root<<1].minn,tr[root<<1|1].minn); } void push_now(int root) { swap(tr[root].maxx,tr[root].minn); tr[root].sum=-tr[root].sum; tr[root].maxx=-tr[root].maxx; tr[root].minn=-tr[root].minn; tr[root].tag^=1; } void push_down(int root) { if(tr[root].tag) { push_now(root<<1); push_now(root<<1|1); tr[root].tag=0; } } void build(int root,int l,int r) { tr[root].l=l; tr[root].r=r; if(l==r) { tr[root].sum=tr[root].maxx=tr[root].minn=a[ys[l]]; return ; } int mid=l+r>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root); } void update1(int root,int l,int r,int x,int key) { if(l==r) { tr[root].sum=tr[root].maxx=tr[root].minn=key; return ; } push_down(root); int mid=l+r>>1; if(x<=mid) update1(root<<1,l,mid,x,key); else update1(root<<1|1,mid+1,r,x,key); push_up(root); } void update2(int root,int l,int r,int L,int R) { if(L>r||R<l) return ; if(L<=l&&r<=R) { push_now(root); return ; } push_down(root); int mid=l+r>>1; if(R<=mid) update2(root<<1,l,mid,L,R); else { if(L>mid) update2(root<<1|1,mid+1,r,L,R); else update2(root<<1,l,mid,L,mid),update2(root<<1|1,mid+1,r,mid+1,R); } push_up(root); } int query_sum(int root,int l,int r,int L,int R) { if(l>R||r<L) return 0; if(L<=l&&r<=R) return tr[root].sum; push_down(root); int mid=l+r>>1; if(R<=mid) return query_sum(root<<1,l,mid,L,R); else { if(L>mid) return query_sum(root<<1|1,mid+1,r,L,R); else return query_sum(root<<1,l,mid,L,mid)+query_sum(root<<1|1,mid+1,r,mid+1,R); } } int query_max(int root,int l,int r,int L,int R) { if(l>R||r<L) return -INF; if(L<=l&&r<=R) return tr[root].maxx; push_down(root); int mid=l+r>>1; if(R<=mid) return query_max(root<<1,l,mid,L,R); else { if(L>mid) return query_max(root<<1|1,mid+1,r,L,R); else return max(query_max(root<<1,l,mid,L,mid),query_max(root<<1|1,mid+1,r,mid+1,R)); } } int query_min(int root,int l,int r,int L,int R) { if(l>R||r<L) return INF; if(L<=l&&r<=R) return tr[root].minn; push_down(root); int mid=l+r>>1; if(R<=mid) return query_min(root<<1,l,mid,L,R); else { if(L>mid) return query_min(root<<1|1,mid+1,r,L,R); else return min(query_min(root<<1,l,mid,L,mid),query_min(root<<1|1,mid+1,r,mid+1,R)); } } void add(int x,int y,int z) { cnt++; edge[cnt].nxt=head[x]; head[x]=cnt; edge[cnt].to=y; edge[cnt].w=z; } inline void dfs1(int p) { siz[p]=1; for(int u=head[p];u!=-1;u=edge[u].nxt) { int to=edge[u].to; if(to==fa[p]) continue; a[to]=edge[u].w,fa[to]=p,depth[to]=depth[p]+1; dfs1(to); siz[p]+=siz[to]; if(siz[to]>siz[son[p]]) son[p]=to; } } inline void dfs2(int p,int tp) { top[p]=tp,ys[dfn[p]=++tot]=p; if(!son[p]) return; dfs2(son[p],tp); for(int u=head[p];u!=-1;u=edge[u].nxt) { int to=edge[u].to; if(to==fa[p]||to==son[p]) continue; dfs2(to,to); } } void change(int x,int y) { while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); update2(1,1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if(depth[x]<depth[y]) swap(x,y); update2(1,1,n,dfn[y]+1,dfn[x]); } int find_sum(int x,int y) { int ret=0; while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); ret+=query_sum(1,1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if(depth[x]<depth[y]) swap(x,y); return ret+query_sum(1,1,n,dfn[y]+1,dfn[x]); } int find_max(int x,int y) { int ret=-INF; while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); ret=max(ret,query_max(1,1,n,dfn[top[x]],dfn[x])); x=fa[top[x]]; } if(depth[x]<depth[y]) swap(x,y); return max(ret,query_max(1,1,n,dfn[y]+1,dfn[x])); } int find_min(int x,int y) { int ret=INF; while(top[x]!=top[y]) { if(depth[top[x]]<depth[top[y]]) swap(x,y); ret=min(ret,query_min(1,1,n,dfn[top[x]],dfn[x])); x=fa[top[x]]; } if(depth[x]<depth[y]) swap(x,y); return min(ret,query_min(1,1,n,dfn[y]+1,dfn[x])); } int find(int x) { return depth[edge[x<<1].to]>depth[edge[x<<1^1].to]?edge[x<<1].to:edge[x<<1^1].to; } int Read() { int i=0,f=1; char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-') f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0'; return i*f; } int main() { memset(head,-1,sizeof(head)); n=Read(); for(int i=1;i<n;++i) { int x=Read()+1,y=Read()+1,z=Read(); add(x,y,z),add(y,x,z); } dfs1(1); dfs2(1,1); build(1,1,n); m=Read(); while(m--) { char cz[5]; scanf("%s",cz); int x=Read(),y=Read(); if(cz[0]=='C') update1(1,1,n,dfn[find(x)],y); if(cz[0]=='N') change(x+1,y+1); if(cz[0]=='S') printf("%d\n",find_sum(x+1,y+1)); if(cz[1]=='A') printf("%d\n",find_max(x+1,y+1)); if(cz[1]=='I') printf("%d\n",find_min(x+1,y+1)); } return 0; }