【bzoj3531】[SDOI2014]旅行
2017-03-02 21:09
344 查看
裸树剖+动态开点线段树.
第一次写动态开点线段树,感觉写了主席树的build+普通线段树的query,其实蛮简单的,以前钊神推荐过,有机会还是多写写.
第一次写动态开点线段树,感觉写了主席树的build+普通线段树的query,其实蛮简单的,以前钊神推荐过,有机会还是多写写.
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> using namespace std; const int N=100010; char s[3]; int qx,n,m,te,sz,q,tot; int num ,size ,tree ,val ,w ,c ; int head ,son ,fa ,h ,tp ,root ; struct edge{ int v,next; }e[200010]; struct seg{ int sum,mx; int l,r,lch,rch; }tr[2000010]; inline int F() { register int aa,bb;register char ch; while(ch=getchar(),(ch<'0'||ch>'9')&&ch!='-');ch=='-'?aa=bb=0:(aa=ch-'0',bb=1); while(ch=getchar(),ch>='0'&&ch<='9')aa=(aa<<3)+(aa<<1)+ch-'0';return bb?aa:-aa; } void add(int u,int v) { e[++te].v=v; e[te].next=head[u]; head[u]=te; } void dfs1(int x) { size[x]=1; for (int i=head[x];i;i=e[i].next) { int v=e[i].v; if (v==fa[x])continue; fa[v]=x; h[v]=h[x]+1; dfs1(v); size[x]+=size[v]; if (size[v]>size[son[x]])son[x]=v; } } void dfs2(int x,int chain) { tp[x]=chain; num[x]=++sz; if (!son[x])return; dfs2(son[x],chain); for (int i=head[x];i;i=e[i].next) { int v=e[i].v; if (v==fa[x]||v==son[x])continue; dfs2(v,v); } } void updata(int k) { tr[k].sum=tr[tr[k].lch].sum+tr[tr[k].rch].sum; tr[k].mx=max(tr[tr[k].lch].mx,tr[tr[k].rch].mx); } void build(int &k,int l,int r,int x,int v) { int mid=(l+r)>>1; if(!k)k=++tot; tr[k].l=l,tr[k].r=r; if (l==r) { tr[k].sum=v; tr[k].mx=v; return; } if (x<=mid)build(tr[k].lch,l,mid,x,v); else build(tr[k].rch,mid+1,r,x,v); updata(k); } void querysum(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if (!k)return; if (x<=l&&r<=y) { qx+=tr[k].sum; return; } int mid=(l+r)>>1; if (x<=mid)querysum(tr[k].lch,x,y); if (y>mid)querysum(tr[k].rch,x,y); } void querymax(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if (!k)return; if (x<=l&&r<=y) { qx=max(qx,tr[k].mx); return; } int mid=(l+r)>>1; // getchar(); // cout<<k<<' '<<x<<' '<<y<<' '<<l<<' '<<r<<' '<<mid<<endl; if (x<=mid)querymax(tr[k].lch,x,y); if (y>mid)querymax(tr[k].rch,x,y); } int solvesum(int x,int y,int st) { qx=0; while(tp[x]!=tp[y]) { if (h[tp[x]]<h[tp[y]])swap(x,y); querysum(root[st],num[tp[x]],num[x]); x=fa[tp[x]]; } if (num[x]>num[y])swap(x,y); querysum(root[st],num[x],num[y]); return qx; } int solvemax(int x,int y,int st) { qx=0; while(tp[x]!=tp[y]) { if (h[tp[x]]<h[tp[y]])swap(x,y); // cout<<111111111<<endl; querymax(root[st],num[tp[x]],num[x]); x=fa[tp[x]]; } if (num[x]>num[y])swap(x,y); // cout<<22222222<<endl; querymax(root[st],num[x],num[y]); return qx; } int main() { int u,v,x,C,y; n=F(),q=F(); for(int i=1;i<=n;++i) w[i]=F(),c[i]=F(); for (int i=1;i<n;++i) u=F(),v=F(),add(u,v),add(v,u); h[1]=1;dfs1(1);dfs2(1,1); for (int i=1;i<=n;++i) build(root[c[i]],1,n,num[i],w[i]); for (int i=1;i<=q;++i) { scanf("%s",s);x=F(),y=F(); if (s[0]=='C'&&s[1]=='C') { build(root[c[x]],1,n,num[x],0); build(root[y],1,n,num[x],w[x]); c[x]=y; } else if (s[0]=='C'&&s[1]=='W') { build(root[c[x]],1,n,num[x],y); w[x]=y; } else if (s[0]=='Q'&&s[1]=='S') printf("%d\n",solvesum(x,y,c[x])); else if (s[0]=='Q'&&s[1]=='M') printf("%d\n",solvemax(x,y,c[x])); } }
相关文章推荐
- [BZOJ3531][SDOI2014]旅行(树剖+线段树)
- BZOJ 3531: [Sdoi2014]旅行( 树链剖分 )
- bzoj 3531: [Sdoi2014]旅行 树链剖分
- [BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】
- bzoj 3531: [Sdoi2014]旅行 线段树+树链剖分
- [bzoj3531][Sdoi2014]旅行 树链剖分
- bzoj3531 [Sdoi2014]旅行
- BZOJ[3531][Sdoi2014]旅行 树链剖分+动态开点线段树
- [BZOJ3531][SDOI2014]旅行(链剖+线段树动态开点)
- [bzoj3531][Sdoi2014][旅行] (主席树+树链剖分)
- 【bzoj 3531】 [Sdoi2014]旅行
- [bzoj 3531]sdoi2014 旅行
- BZOJ 3531 SDOI 2014 旅行
- bzoj 3531: [Sdoi2014]旅行
- [BZOJ3531] [SDOI2014] 旅行
- bzoj3531【SDOI2014】旅行
- bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)
- [BZOJ3531][Sdoi2014]旅行 做题笔记
- 【bzoj3531】[Sdoi2014]旅行
- 【bzoj3531】 [SDOI2014]旅行 树链剖分+动态开点线段树