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;
}

 

posted @ 2021-06-07 14:02  andyc_03  阅读(38)  评论(0编辑  收藏  举报