【树链剖分】【线段树】bzoj2157 旅游
#include<cstdio> #include<algorithm> using namespace std; #define INF 2147483647 #define N 20001 #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r int v[N<<1],first[N],next[N<<1],en,bw[N<<1],dw[N<<1]; void AddEdge(int U,int V,int W) { v[++en]=V; bw[en]=W; next[en]=first[U]; first[U]=en; } int n,fa[N],top[N],tot,dep[N],siz[N],son[N],Num[N],dy[N],m,Map[N]; void dfs(int U) { siz[U]=1; for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]) { dy[(i+1)>>1]=v[i]; dw[v[i]]=bw[i]; fa[v[i]]=U; dep[v[i]]=dep[U]+1; dfs(v[i]); siz[U]+=siz[v[i]]; if(siz[v[i]]>siz[son[U]]) son[U]=v[i]; } } void df2(int U) { Num[U]=++tot; Map[tot]=U; if(son[U]) { top[son[U]]=top[U]; df2(son[U]); } for(int i=first[U];i;i=next[i]) if(v[i]!=fa[U]&&v[i]!=son[U]) { top[v[i]]=v[i]; df2(v[i]); } } int sumv[N<<2],maxv[N<<2],minv[N<<2]; bool rev[N<<2]; void work(int rt) { rev[rt]^=1; sumv[rt]*=(-1); swap(maxv[rt],minv[rt]); maxv[rt]*=(-1); minv[rt]*=(-1); } void pushdown(int rt) { if(rev[rt]) { work(rt<<1); work(rt<<1|1); rev[rt]=0; } } void pushup(int rt) { sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1]; maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]); minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); } void buildtree(int rt,int l,int r) { if(l==r) { sumv[rt]=minv[rt]=maxv[rt]=dw[Map[l]]; return; } int m=(l+r>>1); buildtree(lson); buildtree(rson); pushup(rt); } void update(int p,int v,int rt,int l,int r) { if(l==r) { sumv[rt]=minv[rt]=maxv[rt]=v; return; } pushdown(rt); int m=(l+r>>1); if(p<=m) update(p,v,lson); else update(p,v,rson); pushup(rt); } void reverse(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) { work(rt); return; } int m=(l+r>>1); pushdown(rt); if(ql<=m) reverse(ql,qr,lson); if(m<qr) reverse(ql,qr,rson); pushup(rt); } void Reverse(int U,int V) { while(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); reverse(Num[top[U]],Num[U],1,1,n); U=fa[top[U]]; } if(U!=V) { if(dep[U]>dep[V]) swap(U,V); reverse(Num[U]+1,Num[V],1,1,n); } } int qsum(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return sumv[rt]; int m=(l+r>>1),res=0; pushdown(rt); if(ql<=m) res+=qsum(ql,qr,lson); if(m<qr) res+=qsum(ql,qr,rson); return res; } int Qsum(int U,int V) { int res=0; while(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); res+=qsum(Num[top[U]],Num[U],1,1,n); U=fa[top[U]]; } if(U!=V) { if(dep[U]>dep[V]) swap(U,V); res+=qsum(Num[U]+1,Num[V],1,1,n); } return res; } int qmax(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return maxv[rt]; int m=(l+r>>1),res=-INF; pushdown(rt); if(ql<=m) res=max(res,qmax(ql,qr,lson)); if(m<qr) res=max(res,qmax(ql,qr,rson)); return res; } int Qmax(int U,int V) { int res=-INF; while(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); res=max(res,qmax(Num[top[U]],Num[U],1,1,n)); U=fa[top[U]]; } if(U!=V) { if(dep[U]>dep[V]) swap(U,V); res=max(res,qmax(Num[U]+1,Num[V],1,1,n)); } return res; } int qmin(int ql,int qr,int rt,int l,int r) { if(ql<=l&&r<=qr) return minv[rt]; int m=(l+r>>1),res=INF; pushdown(rt); if(ql<=m) res=min(res,qmin(ql,qr,lson)); if(m<qr) res=min(res,qmin(ql,qr,rson)); return res; } int Qmin(int U,int V) { int res=INF; while(top[U]!=top[V]) { if(dep[top[U]]<dep[top[V]]) swap(U,V); res=min(res,qmin(Num[top[U]],Num[U],1,1,n)); U=fa[top[U]]; } if(U!=V) { if(dep[U]>dep[V]) swap(U,V); res=min(res,qmin(Num[U]+1,Num[V],1,1,n)); } return res; } int main() { char op[4]; int x,y,z; scanf("%d",&n); for(int i=1;i<n;++i) { scanf("%d%d%d",&x,&y,&z); AddEdge(x+1,y+1,z); AddEdge(y+1,x+1,z); } top[1]=1; dfs(1); df2(1); buildtree(1,1,n); scanf("%d",&m); for(;m;--m) { scanf("%s%d%d",op,&x,&y); if(op[0]=='C') update(Num[dy[x]],y,1,1,n); else if(op[0]=='N') Reverse(x+1,y+1); else if(op[0]=='S') printf("%d\n",Qsum(x+1,y+1)); else if(op[1]=='A') printf("%d\n",Qmax(x+1,y+1)); else printf("%d\n",Qmin(x+1,y+1)); } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/