[BZOJ3531]SDOI2014旅行
2015-05-14 09:11
429 查看
先树链剖分,然后为每一个教开一颗线段树,动态开点,没了。
#include<cstdio> #include<iostream> #include<memory.h> #define N 100005 #define M 4000005 using namespace std; struct edge{ int e,next; }ed[N*2]; int n,Q,i,x,y,q,s,e,ne=0,nd=0,cnt,a ,w ,c ,top ,root ,d ,lc[M],rc[M],sum[M],maxw[M],size ,fa ,son ,xu ; char ch[3]; void add(int s,int e) { ed[++ne].e=e;ed[ne].next=a[s];a[s]=ne; } void dfs1(int x) { size[x]=1;son[x]=0; int maxs=0; for (int j=a[x];j;j=ed[j].next) if (ed[j].e!=fa[x]) { fa[ed[j].e]=x;d[ed[j].e]=d[x]+1; dfs1(ed[j].e); size[x]+=size[ed[j].e]; if (size[ed[j].e]>maxs) maxs=size[ed[j].e],son[x]=ed[j].e; } } void dfs2(int x,int t) { xu[x]=++cnt;top[x]=t; if (son[x])dfs2(son[x],t); for (int j=a[x];j;j=ed[j].next) if (ed[j].e!=son[x]&&ed[j].e!=fa[x]) dfs2(ed[j].e,ed[j].e); } void update(int x) { sum[x]=sum[lc[x]]+sum[rc[x]]; maxw[x]=max(maxw[lc[x]],maxw[rc[x]]); } void change(int &x,int l,int r,int t,int q) { if (!x) x=++nd,lc[x]=rc[x]=0; if (l==r) { maxw[x]=sum[x]=q; return; } int mid=(l+r)>>1; if (t<=mid) change(lc[x],l,mid,t,q);else change(rc[x],mid+1,r,t,q); update(x); } void prepare() { fa[1]=0;cnt=0; dfs1(1);dfs2(1,1); memset(root,0,sizeof(root)); sum[0]=maxw[0]=0; for (i=1;i<=n;i++) change(root[c[i]],1,n,xu[i],w[i]); } int qsum(int x,int l,int r,int ll,int rr) { if (!x) return 0; if (ll>r||rr<l) return 0; if (ll<=l&&rr>=r) return sum[x]; int mid=(l+r)>>1; return qsum(lc[x],l,mid,ll,rr)+qsum(rc[x],mid+1,r,ll,rr); } int qmax(int x,int l,int r,int ll,int rr) { if (!x) return 0; if (ll>r||rr<l) return 0; if (ll<=l&&rr>=r) return maxw[x]; int mid=(l+r)>>1; return max(qmax(lc[x],l,mid,ll,rr),qmax(rc[x],mid+1,r,ll,rr)); } void solvesum(int x,int y) { int ans=0,C=c[x]; if (d[top[x]]>d[top[y]]) swap(x,y); while (top[x]!=top[y]) { ans+=qsum(root[C],1,n,xu[top[y]],xu[y]); y=fa[top[y]]; if (d[top[x]]>d[top[y]]) swap(x,y); } ans+=qsum(root[C],1,n,min(xu[x],xu[y]),max(xu[x],xu[y])); printf("%d\n",ans); } void solvemax(int x,int y) { int ans=0,C=c[x]; if (d[top[x]]>d[top[y]]) swap(x,y); while (top[x]!=top[y]) { ans=max(ans,qmax(root[C],1,n,xu[top[y]],xu[y])); y=fa[top[y]]; if (d[top[x]]>d[top[y]]) swap(x,y); } ans=max(ans,qmax(root[C],1,n,min(xu[x],xu[y]),max(xu[x],xu[y]))); printf("%d\n",ans); } int main() { freopen("3531.in","r",stdin); scanf("%d%d",&n,&Q); for (i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]),a[i]=0; for (i=1;i<n;i++) { scanf("%d%d",&s,&e); add(s,e);add(e,s); } prepare(); while (Q--) { scanf("%s%d%d",ch,&x,&y); if (ch[1]=='C') change(root[c[x]],1,n,xu[x],0),c[x]=y,change(root[c[x]],1,n,xu[x],w[x]); else if (ch[1]=='W') w[x]=y,change(root[c[x]],1,n,xu[x],w[x]); else if (ch[1]=='S') solvesum(x,y); else solvemax(x,y); } }
相关文章推荐
- BZOJ 3531 [Sdoi2014]旅行 树链剖分
- BZOJ 3531 [SDOI2014]旅行 树链剖分+线段树
- 【BZOJ3531】[Sdoi2014]旅行 树链剖分+动态开点线段树
- bzoj 3531 [SDOI2014]旅行
- 【SDOI2014】【BZOJ3531】旅行
- [bzoj 3531][SDOI2014]旅行(树链剖分+动态开点线段树)
- [树链剖分 线段树] BZOJ 3531 [Sdoi2014]旅行
- BZOJ 3531 [Sdoi2014]旅行 树链剖分 线段树
- |BZOJ 3531|树链剖分|动态开点线段树|[Sdoi2014]旅行
- BZOJ 3531: [Sdoi2014]旅行
- 【bzoj3531】[Sdoi2014]旅行
- BZOJ 3531 SDOI2014 旅行 树链剖分
- BZOJ 3531 SDOI2014 旅行 树链剖分
- BZOJ 3531: [Sdoi2014]旅行【树剖+动态开点线段树【听说有人写平衡树?【滑稽
- BZOJ 3531: [Sdoi2014]旅行( 树链剖分 )
- 【bzoj3531】[Sdoi2014]旅行
- bzoj 3531: [Sdoi2014]旅行 树链剖分
- 【BZOJ 3531】 [Sdoi2014]旅行
- BZOJ[3531][Sdoi2014]旅行 树链剖分+动态开点线段树
- 【BZOJ3531】【SDOI2014】旅行