BZOJ3681. Arietta
【题意】
【分析】
很明显这种决策的选择我们可以用万能的网络流解决
然后呢,我们发现点数较多,需要用权值线段树合并来优化建图
那么就结束了。。。
【代码】
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=4e6+5; const int maxm=4e6+5; const ll inf=1e17; int S,T,siz; int head[maxn],tot=1,cur[maxn]; struct edge { int to,nxt; ll v; }e[maxm<<1]; void add(int x,int y,ll z) { e[++tot].to=y; e[tot].nxt=head[x]; e[tot].v=z; head[x]=tot; e[++tot].to=x; e[tot].nxt=head[y]; e[tot].v=0; head[y]=tot; } int dep[maxn]; bool bfs() { for(int i=S;i<=siz;i++) cur[i]=head[i],dep[i]=-1; queue <int> q; dep[S]=0; q.push(S); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].nxt) { int to=e[i].to; if(dep[to]!=-1 || !e[i].v) continue; q.push(to); dep[to]=dep[u]+1; } } return (dep[T]!=-1); } ll dfs(int u,ll flow) { if(u==T) return flow; ll res=0; for(int &i=cur[u];i;i=e[i].nxt) { int to=e[i].to; if(dep[to]!=dep[u]+1 || e[i].v<=0) continue; ll tmp=dfs(to,min(e[i].v,flow)); flow-=tmp; res+=tmp; e[i].v-=tmp; e[i^1].v+=tmp; } if(!res) dep[u]=-1; return res; } ll dinic() { ll ans=0; while(bfs()) { ans+=dfs(S,inf); } return ans; } const int N=1e4+5; vector <int> G[N]; int n,m,root[N]; struct segtree { int l,r; }tr[N*70]; void insert(int &rt,int l,int r,int pos) { rt=++siz; if(l==r) { add(rt,T,1); return; } int mid=(l+r)>>1; if(pos<=mid) insert(tr[rt].l,l,mid,pos),add(rt,tr[rt].l,inf); else insert(tr[rt].r,mid+1,r,pos),add(rt,tr[rt].r,inf); } int merge(int x,int y,int l,int r) { if(!x || !y) return x|y; int z=++siz; if(l==r) { add(z,x,inf); add(z,y,inf); return z; } int mid=(l+r)>>1; tr[z].l=merge(tr[x].l,tr[y].l,l,mid); if(tr[z].l) add(z,tr[z].l,inf); tr[z].r=merge(tr[x].r,tr[y].r,mid+1,r); if(tr[z].r) add(z,tr[z].r,inf); return z; } void query(int x,int l,int r,int L,int R,int id) { if(!x) return; if(l>=L && r<=R) { add(id,x,inf); return; } int mid=(l+r)>>1; if(L<=mid) query(tr[x].l,l,mid,L,R,id); if(mid<R) query(tr[x].r,mid+1,r,L,R,id); } void build(int u) { for(auto to:G[u]) { build(to); root[u]=merge(root[u],root[to],1,n); } } int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); scanf("%d%d",&n,&m); int x; for(int i=2;i<=n;i++) { scanf("%d",&x); G[x].push_back(i); } S=0; T=1; siz=1; for(int i=1;i<=n;i++) { scanf("%d",&x); insert(root[i],1,n,x); } build(1); int l,r,d,t; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&l,&r,&d,&t); add(S,++siz,t); query(root[d],1,n,l,r,siz); } printf("%lld",dinic()); return 0; }