Jzoj3625 旅行(travel)
2017-12-13 20:29
375 查看
非常好的树剖模板题了,直接C颗线段树上去就好了,动态开点一次写对~
#pragma GCC opitmize("O3") #pragma G++ opitmize("O3") #include<stdio.h> #include<string.h> #include<algorithm> #define N 100010 #define mid (l+r>>1) using namespace std; struct edge{ int v,nt; } G[200010]; struct nod{ int l,r,s,m; } s[3000010]; int h ,sz ,top ,son ,f ,d ; int n,m,cnt=1,tot=0,clk=0,w ,l ,c ,rt ; inline void gmax(int& x,int y){ x<y?x=y:0; } inline void ps(nod& x){ x.s=s[x.l].s+s[x.r].s; x.m=max(s[x.l].m,s[x.r].m); } inline void adj(int x,int y){ G[++cnt]=(edge){y,h[x]}; h[x]=cnt; G[++cnt]=(edge){x,h[y]}; h[y]=cnt; } void dfs(int x,int p){ d[x]=d[p]+1; sz[x]=1; f[x]=p; for(int v,i=h[x];i;i=G[i].nt) if(!d[v=G[i].v]){ dfs(v,x); sz[x]+=sz[v]; if(sz[v]>sz[son[x]]) son[x]=v; } } void dgs(int x,int p){ top[x]=p; l[x]=++clk; if(son[x]) dgs(son[x],p); for(int v,i=h[x];i;i=G[i].nt) if(!l[v=G[i].v]) dgs(v,v); } void insert(int l,int r,int& x,int p,int k){ if(!x) x=++tot; if(l==r) { s[x].s=s[x].m=k; return; } if(p<=mid) insert(l,mid,s[x].l,p,k); else insert(mid+1,r,s[x].r,p,k); ps(s[x]); } void remove(int l,int r,int& x,int p){ if(l==r){ x=0; return; } if(p<=mid) remove(l,mid,s[x].l,p); else remove(mid+1,r,s[x].r,p); if(s[x].l || s[x].r) ps(s[x]); else x=0; } void modify(int l,int r,int x,int p,int k){ if(l==r){ s[x].s=s[x].m=k; return; } if(p<=mid) modify(l,mid,s[x].l,p,k); else modify(mid+1,r,s[x].r,p,k); ps(s[x]); } int queryS(int l,int r,int x,int L,int R){ if(!x) return 0; if(L<=l && r<=R) return s[x].s; int ans=0; if(L<=mid) ans+=queryS(l,mid,s[x].l,L,R); if(mid<R) ans+=queryS(mid+1,r,s[x].r,L,R); return ans; } int gSum(int x,int y){ int ans=0,C=c[x]; for(;top[x]!=top[y];y=f[top[y]]){ if(d[top[x]]>d[top[y]]) swap(x,y); ans+=queryS(1,n,rt[C],l[top[y]],l[y]); } if(d[x]>d[y]) swap(x,y); return ans+queryS(1,n,rt[C],l[x],l[y]); } int queryM(int l,int r,int x,int L,int R){ if(!x) return 0; if(L<=l && r<=R) return s[x].m; int ans=0; if(L<=mid) gmax(ans,queryM(l,mid,s[x].l,L,R)); if(mid<R) gmax(ans,queryM(mid+1,r,s[x].r,L,R)); return ans; } int gMax(int x,int y){ int ans=0,C=c[x]; for(;top[x]!=top[y];y=f[top[y]]){ if(d[top[x]]>d[top[y]]) swap(x,y); gmax(ans,queryM(1,n,rt[C],l[top[y]],l[y])); } if(d[x]>d[y]) swap(x,y); return max(ans,queryM(1,n,rt[C],l[x],l[y])); } int main(){ freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d%d",w+i,c+i); for(int x,y,i=1;i<n;++i) scanf("%d%d",&x,&y),adj(x,y); dfs(1,0); dgs(1,1); char o[3]; for(int i=1;i<=n;++i) insert(1,n,rt[c[i]],l[i],w[i]); for(int x,y;m--;){ scanf("%s%d%d",o,&x,&y); if(*o=='C'){ if(o[1]=='C'){ remove(1,n,rt[c[x]],l[x]); insert(1,n,rt[y],l[x],w[x]); c[x]=y; } else { modify(1,n,rt[c[x]],l[x],y); w[x]=y; } } else { if(o[1]=='S') printf("%d\n",gSum(x,y)); else printf("%d\n",gMax(x,y)); } } }
相关文章推荐
- 【jzoj3625】【SDOI2014】【旅行(travel)】 【虚树】【lct】
- [SDOI 2014] [JZOJ 3625] 旅行
- JZOJ3847. 【NOIP2014八校联考第1场第2试9.21】都市环游(travel)
- JZOJ 3053. 旅行
- [JZOJ 1281]旅行
- openjudge 旅行(travel.cpp/1000ms/128M)
- 【jzoj3101】【NOIP2012提高组】【开车旅行】
- [JZOJ5177]【NOIP2017提高组模拟6.28】TRAVEL
- JZOJ1315.【USACO题库】5.2.1 Snail Trails蜗牛的旅行
- 【动规递推】旅行(travel.pas/c/cpp)
- 【SDOI2015】【BZOJ4086】旅行计划travel
- JZOJ3053. 【NOIP2012模拟10.25】旅行
- [Codeforces 487E]Tourists/[JZOJ4691]旅行/[UOJ#30]Tourists
- 【JZOJ3503】旅行
- JZOJ 1329——旅行【贪心】
- jzoj 1402. 【2012.03.09普及组】旅行
- 旅行 jzoj 1281
- 【JZOJ 3053】旅行
- JZOJ 1329. 旅行
- JZOJ 5177. 【NOIP2017提高组模拟6.28】TRAVEL