【BZOJ3531】旅行(线段树)
2017-07-20 10:31
495 查看
传送门
算法:线段树(动态开点)+树链剖分
实现:对每一种c2(信仰)建立线段树,维护以之为信仰的城市的c1。
Attention!
1)动态删点要带&
2)对于每一个修改操作,不仅在线段树上更改,还要更改原数组的值。
I Think
题意:一棵树上节点有两个点权c1,c2,求(x,y)两点路径中c2与x的c2相同的城市的c1总和/最大值,两个点权均带修改。算法:线段树(动态开点)+树链剖分
实现:对每一种c2(信仰)建立线段树,维护以之为信仰的城市的c1。
Attention!
1)动态删点要带&
2)对于每一个修改操作,不仅在线段树上更改,还要更改原数组的值。
Code
#include<cstdio> using namespace std; const int sm = 1e5+2; const int sn = sm<<6; template <typename T> void read(T &x) { char ch=getchar();x=0; while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); } char Hint[3]; int N,Q,tot,t; int sum[sn],mx[sn],c[sm],w[sm],T[sm],stk[sm]; int hd[sm],to[sm<<1],nxt[sm<<1],Ls[sn],Rs[sn]; int Fa[sm][18],dep[sm],son[sm],sz[sm],top[sm],pl[sm]; void Swap(int &x,int &y) { int t=x;x=y;y=t; } int Max(int x,int y) { return x>y?x:y; } void Add(i 4000 nt u,int v) { to[++tot]=v,nxt[tot]=hd[u],hd[u]=tot; to[++tot]=u,nxt[tot]=hd[v],hd[v]=tot; } void Dfsa(int x,int fa) { Fa[x][0]=fa,dep[x]=dep[fa]+1,sz[x]=1; for(int i=1;i<=17;++i) if(Fa[x][i-1])Fa[x][i]=Fa[Fa[x][i-1]][i-1]; else break; for(int i=hd[x];i;i=nxt[i]) if(to[i]!=fa) { Dfsa(to[i],x),sz[x]+=sz[to[i]]; if(sz[son[x]]<sz[to[i]])son[x]=to[i]; } } void Dfsb(int x,int tp) { pl[x]=++tot,top[x]=tp; if(son[x]) Dfsb(son[x],top[x]); for(int i=hd[x];i;i=nxt[i]) if(to[i]!=Fa[x][0]&&to[i]!=son[x]) Dfsb(to[i],to[i]); } void Up(int rt) { mx[rt]=Max(mx[Ls[rt]],mx[Rs[rt]]); sum[rt]=sum[Ls[rt]]+sum[Rs[rt]]; } void del(int &rt) { stk[++t]=rt,mx[rt]=sum[rt]=0,rt=0; } void Modify(int &rt,int l,int r,int p,int val) { if(!rt) { if(t) rt=stk[t--]; else rt=++tot;} if(l==r) { mx[rt]=sum[rt]=val; if(!mx[rt])del(rt); return; } int m=(l+r)>>1; if(p<=m) Modify(Ls[rt],l,m,p,val); else Modify(Rs[rt],m+1,r,p,val); if(!Ls[rt]&&!Rs[rt]) del(rt); else Up(rt); } int Maxn(int rt,int l,int r,int a,int b) { if(!rt||l>b||r<a) return 0; if(a<=l&&r<=b) return mx[rt]; int m=(l+r)>>1,ans=0; if(a<=m) ans=Max(ans,Maxn(Ls[rt],l,m,a,b)); if(b> m) ans=Max(ans,Maxn(Rs[rt],m+1,r,a,b)); return ans; } int Sum(int rt,int l,int r,int a,int b) { if(!rt)return 0; if(a<=l&&r<=b) return sum[rt]; int m=(l+r)>>1,ans=0; if(a<=m) ans+=Sum(Ls[rt],l,m,a,b); if(b> m) ans+=Sum(Rs[rt],m+1,r,a,b); return ans; } int Q_max(int a,int b) { int og=T[c[a]],tmp=0; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]])Swap(a,b); tmp=Max(tmp,Maxn(og,1,N,pl[top[a]],pl[a])); a=Fa[top[a]][0]; } if(pl[a]>pl[b]) Swap(a,b); tmp=Max(tmp,Maxn(og,1,N,pl[a],pl[b])); return tmp; } int Q_sum(int a,int b) { int og=T[c[a]],ret=0; while(top[a]!=top[b]) { if(dep[top[a]]<dep[top[b]]) Swap(a,b); ret+=Sum(og,1,N,pl[top[a]],pl[a]); a=Fa[top[a]][0]; } if(pl[a]>pl[b])Swap(a,b); ret+=Sum(og,1,N,pl[a],pl[b]); return ret; } int Lca(int u,int v) { if(dep[u]!=dep[v]) { if(dep[u]<dep[v]) Swap(u,v); for(int i=17;i>=0;--i) if(dep[Fa[u][i]]>dep[v]) u=Fa[u][i]; u=Fa[u][0]; } if(u==v) return v; for(int i=17;i>=0;--i) if(Fa[u][i]!=Fa[v][i]) u=Fa[u][i],v=Fa[v][i]; return Fa[u][0]; } int main() { read(N),read(Q); for(int i=1;i<=N;++i) read(w[i]),read(c[i]); for(int i=1,a,b;i<N;++i) read(a),read(b),Add(a,b); tot=0,Dfsa(1,0),Dfsb(1,1),tot=0; for(int i=1;i<=N;++i) Modify(T[c[i]],1,N,pl[i],w[i]); for(int i=1,x,y,lc,S;i<=Q;++i) { scanf("%s",Hint); read(x),read(y); if(Hint[0]=='C') { if(Hint[1]=='C') { Modify(T[c[x]],1,N,pl[x],0),c[x]=y; Modify(T[c[x]],1,N,pl[x],w[x]); } else Modify(T[c[x]],1,N,pl[x],y),w[x]=y;//别忘记更新 } else{ lc=Lca(x,y); if(Hint[1]=='S') printf("%d\n",Q_sum(x,lc)+Q_sum(y,lc)-(c[lc]==c[x])*w[lc]); else printf("%d\n",Max(Q_max(x,lc),Q_max(y,lc))); } } return 0; }
相关文章推荐
- BZOJ 3531 旅行 (树链剖分 + 线段树动态开点)
- bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)
- 【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行
- 【BZOJ3531】旅行(树链剖分,线段树)
- BZOJ 3531 [Sdoi2014]旅行 树链剖分 线段树
- [BZOJ3531][SDOI2014]旅行(树剖+线段树)
- 【BZOJ3531】旅行,树链剖分+开点线段树
- BZOJ-3531 旅行 树链剖分+动态开点线段树
- 树链剖分+动态线段树(BZOJ-3531旅行)
- BZOJ 3531: [Sdoi2014]旅行【树剖+动态开点线段树【听说有人写平衡树?【滑稽
- 【bzoj3531】[Sdoi2014]旅行 动态开点的线段树
- |BZOJ 3531|树链剖分|动态开点线段树|[Sdoi2014]旅行
- 【bzoj3531】 [SDOI2014]旅行 树链剖分+动态开点线段树
- [树链剖分 线段树] BZOJ 3531 [Sdoi2014]旅行
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
- BZOJ[3531][Sdoi2014]旅行 树链剖分+动态开点线段树
- [BZOJ3531] [SDOI2014] 旅行
- BZOJ 3531 旅行【树链剖分】
- 【bzoj3531】[Sdoi2014]旅行