[dsu on tree 主席树优化建图 最大流] BZOJ 3681 Arietta
2017-04-10 22:39
337 查看
这显然是个类似二分图匹配
但直接跑网络流边数承受不了
我们采用套路 用数据结构优化建图 类似vfk的a+b problem
我们处理子树问题 有一种方法是按dfs序建主席树 然后就可以用减法取出一段区间 也就是子树的信息
但是在某些情况下不能减 比如在这个网络流里 这样的话 我们就要用一种科技 dsu on tree
相关资料 原文 神犇翻译版本
大概意思是 我们用重链剖分的思想
当前子树的线段树是基于重儿子的线段树然后加上所有轻儿子往下的子孙
看起来很暴力 其实每个点作为轻儿子的子孙的次数是O(logn)的 也就是向上轻边的数量 这样我们就得到了每一个子树的线段树版本 而不是通过减法得出信息
复杂度大概是O(nlog2n)
这样点数边数就都能承受了 跑一发网络流
这题卡内存啊
但直接跑网络流边数承受不了
我们采用套路 用数据结构优化建图 类似vfk的a+b problem
我们处理子树问题 有一种方法是按dfs序建主席树 然后就可以用减法取出一段区间 也就是子树的信息
但是在某些情况下不能减 比如在这个网络流里 这样的话 我们就要用一种科技 dsu on tree
相关资料 原文 神犇翻译版本
大概意思是 我们用重链剖分的思想
当前子树的线段树是基于重儿子的线段树然后加上所有轻儿子往下的子孙
看起来很暴力 其实每个点作为轻儿子的子孙的次数是O(logn)的 也就是向上轻边的数量 这样我们就得到了每一个子树的线段树版本 而不是通过减法得出信息
复杂度大概是O(nlog2n)
这样点数边数就都能承受了 跑一发网络流
这题卡内存啊
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } namespace D{ const int M=2500005; const int N=1300005; struct edge{ int v,f,next; }G[M]; int head ,inum=1; inline void add(int u,int v,int f,int p){ /*G[p].u=u;*/ G[p].v=v; G[p].f=f; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int f){ add(u,v,f,++inum); add(v,u,0,++inum); } int S,T; int Q ,l,r; int dis ; #define V G[p].v inline bool bfs(){ for (int i=1;i<=T;i++) dis[i]=-1; l=r=-1; Q[++r]=S; dis[S]=0; while (l<r){ int u=Q[++l]; for (int p=head[u];p;p=G[p].next) if (G[p].f && dis[V]==-1){ dis[V]=dis[u]+1; Q[++r]=V; if (V==T) return 1; } } return 0; } int cur ; inline int dfs(int u,int flow){ if (u==T) return flow; int used=0; for (int p=cur[u];p;p=G[p].next){ cur[u]=p; if (G[p].f && dis[V]==dis[u]+1){ int d=dfs(V,min(flow-used,G[p].f)); G[p].f-=d; G[p^1].f+=d; used+=d; if (used==flow) break; } } if (!used) dis[u]=-1; return used; } inline int Dinic(){ int ret=0; while (bfs()){ memcpy(cur,head,sizeof(int)*(T+5)); ret+=dfs(S,1<<30); } return ret; } } const int N=10005; struct edge{ int u,v,next; }G[N<<1]; int head ,inum; inline void add(int u,int v,int p){ G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p; } const int M=1300005; int ncnt; int rt ,ls[M],rs[M]; inline void Add(int &x,int y,int l,int r,int t,int idx){ x=++ncnt; int mid=(l+r)>>1; if (y) D::link(x,y,1<<30); if (l==r){ D::link(x,idx,1<<30); return; } if (t<=mid) rs[x]=rs[y],Add(ls[x],ls[y],l,mid,t,idx); else ls[x]=ls[y],Add(rs[x],rs[y],mid+1,r,t,idx); } inline void Link(int x,int l,int r,int ql,int qr,int idx){ if (!x) return; if (ql<=l && r<=qr){ D::link(idx,x,1<<30); return; } int mid=(l+r)>>1; if (ql<=mid) Link(ls[x],l,mid,ql,qr,idx); if (qr>mid) Link(rs[x],mid+1,r,ql,qr,idx); } int n,m,Q; int val ,size ; int last,cur; inline void mer(int u){ Add(cur,last,1,n,val[u],u); last=cur; for (int p=head[u];p;p=G[p].next) mer(V); } inline void dfs(int u){ size[u]=1; int son=0,maxv=0; for (int p=head[u];p;p=G[p].next){ dfs(V),size[u]+=size[V]; if (size[V]>maxv) maxv=size[son=V]; } last=rt[son]; Add(cur,last,1,n,val[u],u); last=cur; for (int p=head[u];p;p=G[p].next) if (V!=son) mer(V); rt[u]=last; } int main(){ int x,l,r,t; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(Q); for (int i=2;i<=n;i++) read(x),add(x,i,++inum); for (int i=1;i<=n;i++) read(val[i]); ncnt=n; dfs(1); for (int i=n+1;i<=ncnt;i++){ if (ls[i]) D::link(i,ls[i],1<<30); if (rs[i]) D::link(i,rs[i],1<<30); } D::S=ncnt+Q+1; D::T=ncnt+Q+2; for (int i=1;i<=n;i++) D::link(i,D::T,1); for (int i=1;i<=Q;i++){ read(l); read(r); read(x); read(t); D::link(D::S,ncnt+i,t); Link(rt[x],1,n,l,r,ncnt+i); } printf("%d\n",D::Dinic()); return 0; }
相关文章推荐
- bzoj 3681: Arietta 主席树优化建图+网络流+dsu on tree
- 【BZOJ3681】Arietta,主席树优化网络流
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
- bzoj 2588 Spoj 10628 Count on a tree 树链剖分 主席树
- BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]
- BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )
- bzoj 2588 Spoj 10628. Count on a tree(主席树)
- BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- bzoj2588 count on a tree 主席树
- BZOJ 2588: Spoj 10628. Count on a tree 主席树+lca
- 【主席树】bzoj2588 Spoj 10628. Count on a tree
- BZOJ 2588 Count On a Tree 【LCA】【主席树】
- 【BZOJ-2588】Count on a tree 主席树 + 倍增
- 【BZOJ2588】Count on a tree,主席树维护链+ST表求LCA
- [主席树] BZOJ 1803 Spoj1487 Query on a tree III
- bzoj2588: Spoj 10628. Count on a tree 主席树+dfs序
- bzoj 1803: Spoj1487 Query on a tree III(主席树)