【BZOJ4353】Play with tree,树链剖分线段树
2016-09-13 20:52
351 查看
传送门
思路:
毒瘤数据结构
维护区间最小值及个数,区间0的个数
标记分为覆盖标记和增值标记
1操作直接覆盖
2操作取路径最小值,再判断增值
边链剖注意减去1节点的贡献
细节太多全靠自己
我反正是写了2h……
思路:
毒瘤数据结构
维护区间最小值及个数,区间0的个数
标记分为覆盖标记和增值标记
1操作直接覆盖
2操作取路径最小值,再判断增值
边链剖注意减去1节点的贡献
细节太多全靠自己
我反正是写了2h……
#include<cstdio> #include<iostream> #include<cstring> #define M 100005 #define LL long long using namespace std; int n,m,tot,cnt; int first[M],siz[M],top[M],son[M],pre[M],L[M],fa[M],sum[M<<2],dep[M],mi_sum[M<<2]; LL mi[M<<2],lazy[M<<2],cover[M<<2]; int in() { char ch=getchar();int t=0;bool f=0; while (ch<'0'||ch>'9') f=(ch=='-'),ch=getchar(); while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar(); return f?-t:t; } struct edge{ int u,v,next,w; }e[M<<1]; void add(int x,int y,int z) { e[++tot]=(edge){x,y,first[x],z};first[x]=tot; e[++tot]=(edge){y,x,first[y],z};first[y]=tot; } void dfs1(int x) { siz[x]=1; for (int i=first[x];i;i=e[i].next) if (e[i].v!=fa[x]) fa[e[i].v]=x, dep[e[i].v]=dep[x]+1, dfs1(e[i].v), siz[x]+=siz[e[i].v], son[x]=(siz[son[x]]<siz[e[i].v]?e[i].v:son[x]); } void dfs2(int x,int tp) { L[x]=++cnt; pre[cnt]=x; top[x]=tp; if (son[x]) dfs2(son[x],tp); else return; for (int i=first[x];i;i=e[i].next) if (e[i].v!=fa[x]&&e[i].v!=son[x]) dfs2(e[i].v,e[i].v); } void build(int rt,int begin,int end) { mi_sum[rt]=sum[rt]=end-begin+1; if (begin==end) return; int mid=begin+end>>1; build(rt<<1,begin,mid); build(rt<<1|1,mid+1,end); } void pushdown(int rt,int begin,int end) { int mid=begin+end>>1; if (cover[rt]!=-1) { lazy[rt]=lazy[rt<<1]=lazy[rt<<1|1]=0; cover[rt<<1]=cover[rt<<1|1]=cover[rt]; mi[rt<<1]=mi[rt<<1|1]=cover[rt]; mi_sum[rt<<1]=mid-begin+1; mi_sum[rt<<1|1]=end-mid; if (!cover[rt]) sum[rt<<1]=mid-begin+1, sum[rt<<1|1]=end-mid; else sum[rt<<1]=sum[rt<<1|1]=0; cover[rt]=-1; } else if (lazy[rt]) { if (cover[rt<<1]!=-1) cover[rt<<1]+=lazy[rt]; else lazy[rt<<1]+=lazy[rt]; if (cover[rt<<1|1]!=-1) cover[rt<<1|1]+=lazy[rt]; else lazy[rt<<1|1]+=lazy[rt]; mi[rt<<1]+=lazy[rt]; if (!mi[rt<<1]) sum[rt<<1]=mi_sum[rt<<1]; else sum[rt<<1]=0; mi[rt<<1|1]+=lazy[rt]; if (!mi[rt<<1|1]) sum[rt<<1|1]=mi_sum[rt<<1|1]; else sum[rt<<1|1]=0; lazy[rt]=0; } } void pushup(int rt,int begin,int end) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; if (mi[rt<<1]==mi[rt<<1|1]) mi_sum[rt]=mi_sum[rt<<1]+mi_sum[rt<<1|1]; else mi_sum[rt]=(mi[rt<<1]>mi[rt<<1|1]?mi_sum[rt<<1|1]:mi_sum[rt<<1]); mi[rt]=min(mi[rt<<1],mi[rt<<1|1]); } void Seg_fill(int rt,int begin,int end,int l,int r,int val) { if (l<=begin&&end<=r) { sum[rt]=(val?0:end-begin+1); mi[rt]=val;mi_sum[rt]=end-begin+1; lazy[rt]=0;cover[rt]=val; return; } pushdown(rt,begin,end); int mid=begin+end>>1; if (mid>=l) Seg_fill(rt<<1,begin,mid,l,r,val); if (mid<r) Seg_fill(rt<<1|1,mid+1,end,l,r,val); pushup(rt,begin,end); } LL Seg_min(int rt,int begin,int end,int l,int r) { if (l<=begin&&end<=r) return mi[rt]; pushdown(rt,begin,end); int mid=begin+end>>1;LL ans=1LL<<60; if (mid>=l) ans=min(ans,Seg_min(rt<<1,begin,mid,l,r)); if (mid<r) ans=min(ans,Seg_min(rt<<1|1,mid+1,end,l,r)); return ans; } void Seg_pls(int rt,int begin,int end,int l,int r,LL val) { if (l<=begin&&end<=r) { mi[rt]+=val; sum[rt]=(mi[rt]?0:mi_sum[rt]); if (cover[rt]!=-1) cover[rt]+=val; else lazy[rt]+=val; return; } pushdown(rt,begin,end); int mid=begin+end>>1; if (mid>=l) Seg_pls(rt<<1,begin,mid,l,r,val); if (mid<r) Seg_pls(rt<<1|1,mid+1,end,l,r,val); pushup(rt,begin,end); } void fill(int u,int v,int c) { for (;top[u]!=top[v];u=fa[top[u]]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); Seg_fill(1,1,n,L[top[u]],L[u],c); } if (dep[u]>dep[v]) swap(u,v); else if (dep[u]==dep[v]) return; u=son[u]; Seg_fill(1,1,n,L[u],L[v],c); } LL get_min(int u,int v) { LL ans=1LL<<60; for (;top[u]!=top[v];u=fa[top[u]]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); ans=min(ans,Seg_min(1,1,n,L[top[u]],L[u])); } if (dep[u]>dep[v]) swap(u,v); else if (dep[u]==dep[v]) return ans; u=son[u]; return min(ans,Seg_min(1,1,n,L[u],L[v])); } void pls(int u,int v,LL c) { for (;top[u]!=top[v];u=fa[top[u]]) { if (dep[top[u]]<dep[top[v]]) swap(u,v); Seg_pls(1,1,n,L[top[u]],L[u],c); } if (dep[u]>dep[v]) swap(u,v); else if (dep[u]==dep[v]) return; u=son[u]; Seg_pls(1,1,n,L[u],L[v],c); } main() { n=in();m=in(); for (int i=1;i<n;++i) add(in(),in(),0); dfs1(1); dfs2(1,1); build(1,1,n); memset(cover,-1,sizeof(cover)); for (int p,u,v,c;m;--m) { p=in();u=in();v=in();c=in(); if (p==1) fill(u,v,c); else p=get_min(u,v), pls(u,v,p+c<0?-p:c); printf("%d\n",sum[1]-(Seg_min(1,1,n,L[1],L[1])==0)); } }
相关文章推荐
- bzoj 4353: Play with tree (树链剖分)
- [BZOJ4353]Play with tree(树链剖分+线段树)
- bzoj4353: Play with tree
- 【Bzoj4353】play with tree
- 【 bzoj 4355 】 Play with sequence - 线段树乱搞
- 【BZOJ4355】Play with sequence 线段树
- bzoj 4355: Play with sequence (线段树)
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
- bzoj 3221: Obserbing the tree树上询问 树链剖分+线段树
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
- [bzoj4127]Abs_树链剖分_线段树
- 动态树LCT||树链剖分+线段树(SPOJ QTREE3 - Query on a tree again!)
- spoj 375 Query on a tree(树链剖分,边,线段树)
- BZOJ 4034 [HAOI2015]T2 树链剖分+线段树
- BZOJ 3221 [Codechef FEB13] Obserbing the tree树上询问 树链剖分 主席树维护区间加等差数列
- BZOJ 2243 [SDOI2011]染色 (树链剖分)(线段树区间修改)
- 【BZOJ4034】[HAOI2015]T2【树链剖分】【线段树】
- 【SPOJ】QTREE - Query on a tree(树链剖分+线段树(基于边权))
- Hdu 3804 Query on a tree 树链剖分+线段树
- 【BZOJ1984】月下“毛景树” 树链剖分+线段树