bzoj 2157: 旅遊【樹鏈剖分+線段樹】
阿新 • • 發佈:2018-09-11
ios else add n) -- lse names for swa
裸的樹鏈剖分+線段樹
但是要註意一個地方……我WA了好幾次才發現取完相反數之後max值和min值是要交換的……
#include<iostream> #include<cstdio> using namespace std; const int N=200005; int n,m,h[N],cnt,de[N],va[N],fa[N],si[N],hs[N],fr[N],id[N],tot,rl[N]; char c[10]; struct qwe { int ne,no,to,va; }e[N<<1]; struct xds { int l,r,mn,mx,sm,lz; }t[N<<1]; int read() { int r=0,f=1; char p=getchar(); while(p>‘9‘||p<‘0‘) { if(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].no=u; e[cnt].to=v; e[cnt].va=w; h[u]=cnt; } void dfs1(int u,int fat) { fa[u]=fat; si[u]=1; de[u]=de[fat]+1; for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fat) { va[e[i].to]=e[i].va; dfs1(e[i].to,u); si[u]+=si[e[i].to]; if(si[e[i].to]>si[hs[u]]) hs[u]=e[i].to; } } void dfs2(int u,int top) { fr[u]=top; id[u]=++tot; rl[tot]=u; if(!hs[u]) return; dfs2(hs[u],top); for(int i=h[u];i;i=e[i].ne) if(e[i].to!=fa[u]&&e[i].to!=hs[u]) dfs2(e[i].to,e[i].to); } void ud(int ro) { t[ro].mn=min(t[ro<<1].mn,t[ro<<1|1].mn); t[ro].mx=max(t[ro<<1].mx,t[ro<<1|1].mx); t[ro].sm=t[ro<<1].sm+t[ro<<1|1].sm; } void pd(int ro) { if(t[ro].lz) { t[ro<<1].mn*=-1,t[ro<<1].mx*=-1,t[ro<<1].sm*=-1,swap(t[ro<<1].mn,t[ro<<1].mx); t[ro<<1|1].mn*=-1,t[ro<<1|1].mx*=-1,t[ro<<1|1].sm*=-1,swap(t[ro<<1|1].mn,t[ro<<1|1].mx); t[ro<<1].lz^=1; t[ro<<1|1].lz^=1; t[ro].lz=0; } } void build(int ro,int l,int r) { t[ro].l=l,t[ro].r=r; if(l==r) { t[ro].mn=t[ro].mx=t[ro].sm=va[rl[l]]; return; } int mid=(l+r)>>1; build(ro<<1,l,mid); build(ro<<1|1,mid+1,r); ud(ro); } void xiu(int ro,int p,int v) { if(t[ro].l==t[ro].r) { t[ro].mn=t[ro].mx=t[ro].sm=v; return; } pd(ro); int mid=(t[ro].l+t[ro].r)>>1; if(p<=mid) xiu(ro<<1,p,v); else xiu(ro<<1|1,p,v); ud(ro); } void update(int ro,int l,int r) { if(t[ro].l==l&&t[ro].r==r) { t[ro].mn*=-1,t[ro].mx*=-1,t[ro].sm*=-1,swap(t[ro].mn,t[ro].mx); t[ro].lz^=1; return; } pd(ro); int mid=(t[ro].l+t[ro].r)>>1; if(r<=mid) update(ro<<1,l,r); else if(l>mid) update(ro<<1|1,l,r); else update(ro<<1,l,mid),update(ro<<1|1,mid+1,r); ud(ro); } void gai(int u,int v) { while(fr[u]!=fr[v]) { if(de[fr[u]]<de[fr[v]]) swap(u,v); update(1,id[fr[u]],id[u]); u=fa[fr[u]]; } if(u!=v) { if(de[u]>de[v]) swap(u,v); update(1,id[u]+1,id[v]); } } int quessum(int ro,int l,int r) {//cerr<<t[ro].l<<" "<<t[ro].r<<" "<<l<<" "<<r<<endl; if(t[ro].l==l&&t[ro].r==r) return t[ro].sm; pd(ro); int mid=(t[ro].l+t[ro].r)>>1; if(r<=mid) return quessum(ro<<1,l,r); else if(l>mid) return quessum(ro<<1|1,l,r); else return quessum(ro<<1,l,mid)+quessum(ro<<1|1,mid+1,r); } int wensum(int u,int v) { int r=0;//cerr<<"fr"<<fr[u]<<" "<<fr[v]<<endl; while(fr[u]!=fr[v]) { if(de[fr[u]]<de[fr[v]]) swap(u,v);//cerr<<fr[u]<<" "<<u<<endl; r+=quessum(1,id[fr[u]],id[u]); u=fa[fr[u]]; } if(u!=v) { if(de[u]>de[v]) swap(u,v);//cerr<<u<<" "<<v<<endl; r+=quessum(1,id[u]+1,id[v]); } return r; } int quesmax(int ro,int l,int r) { if(t[ro].l==l&&t[ro].r==r) return t[ro].mx; pd(ro); int mid=(t[ro].l+t[ro].r)>>1; if(r<=mid) return quesmax(ro<<1,l,r); else if(l>mid) return quesmax(ro<<1|1,l,r); else return max(quesmax(ro<<1,l,mid),quesmax(ro<<1|1,mid+1,r)); } int wenmax(int u,int v) { int r=-1e9; while(fr[u]!=fr[v]) { if(de[fr[u]]<de[fr[v]]) swap(u,v); r=max(r,quesmax(1,id[fr[u]],id[u])); u=fa[fr[u]]; } if(u!=v) { if(de[u]>de[v]) swap(u,v); r=max(r,quesmax(1,id[u]+1,id[v])); } return r; } int quesmin(int ro,int l,int r) { if(t[ro].l==l&&t[ro].r==r) return t[ro].mn; pd(ro); int mid=(t[ro].l+t[ro].r)>>1; if(r<=mid) return quesmin(ro<<1,l,r); else if(l>mid) return quesmin(ro<<1|1,l,r); else return min(quesmin(ro<<1,l,mid),quesmin(ro<<1|1,mid+1,r)); } int wenmin(int u,int v) { int r=1e9; while(fr[u]!=fr[v]) { if(de[fr[u]]<de[fr[v]]) swap(u,v); r=min(r,quesmin(1,id[fr[u]],id[u])); u=fa[fr[u]]; } if(u!=v) { if(de[u]>de[v]) swap(u,v); r=min(r,quesmin(1,id[u]+1,id[v])); } return r; } int main() { 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,0); dfs2(1,1); build(1,1,n); m=read(); while(m--) { scanf("%s",c); int x=read(),y=read(); if(c[0]==‘C‘) xiu(1,de[e[x<<1].no]>de[e[x<<1].to]?id[e[x<<1].no]:id[e[x<<1].to],y); if(c[0]==‘N‘) gai(x+1,y+1); if(c[1]==‘U‘) printf("%d\n",wensum(x+1,y+1)); if(c[1]==‘A‘) printf("%d\n",wenmax(x+1,y+1)); if(c[1]==‘I‘) printf("%d\n",wenmin(x+1,y+1)); } return 0; }
bzoj 2157: 旅遊【樹鏈剖分+線段樹】