zoukankan      html  css  js  c++  java
  • BZOJ 3681: Arietta

    数据结构优化建图的网络流,还需要Dsu on tree可持久化,但也不大难写

    很容易想出暴力的做法,把操作和音符看作二分图,然后就是求一个最大匹配,转化一下就是一个最大流

    此时的边数目是(O(nm))的,显然需要优化边数

    树上子树内信息的维护般就那么几种,这里DFS+主席树上树无法维护(因为颜色不是可减的),那么我们考虑静态科技Dsu on tree

    这道题里面我们要给每个点开可持久化线段树,线段树的下标是颜色,这样可以实现某个点子树内的连边操作

    那么怎么维护呢,根据Dsu on tree的思想,我们做到一个点时就把它重儿子的线段树继承过来,然后暴力把轻儿子一个一个加进去

    由于Dsu on tree的复杂度是(O(nlog n))的(每个点做为轻儿子的次数是(log)级别的),线段树每次新建(log n)个节点,因此总边数是(O(nlog^2 n))

    然后跑一跑网络流就好了,根据Dinic跑二分图的效率以及网络流跑不满的特性可以卡过此题

    PS:这题又卡时间又卡内存,可谓毒瘤至极

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define RI register int
    #define CI const int&
    using namespace std;
    const int N=10005,INF=1e9;
    struct edge
    {
        int to,nxt,v;
    }e[N]; int n,m,cnt,head[N],x,a[N],rt[N],size[N],son[N],l,r,t,tot,lst,cur; 
    inline void addedge(CI x,CI y)
    {
        e[++cnt]=(edge){y,head[x],0}; head[x]=cnt;
    }
    #define to e[i].to
    namespace NF //Network Flow
    {
        const int N=1300005,M=2500005;
        edge e[M]; int cnt=1,head[N],cur[N],q[N],dep[N],s,t;
        inline void addedge(CI x,CI y,CI z)
        {
            e[++cnt]=(edge){y,head[x],z}; head[x]=cnt;
            e[++cnt]=(edge){x,head[y],0}; head[y]=cnt;
        }
        inline bool BFS(void)
        {
            RI H=0,T=1; memset(dep,0,t+1<<2); q[dep[s]=1]=s;
            while (H<T)
            {
                int now=q[++H]; for (RI i=head[now];i;i=e[i].nxt)
                if (e[i].v&&!dep[to]) dep[to]=dep[now]+1,q[++T]=to;
            }
            return dep[t];
        }
        inline int DFS(CI now,CI tar,int dis)
        {
            if (now==tar) return dis; int ret=0;
            for (RI& i=cur[now];i&&dis;i=e[i].nxt)
            if (e[i].v&&dep[to]==dep[now]+1)
            {
                int dist=DFS(to,tar,min(dis,e[i].v));
                dis-=dist; ret+=dist; e[i].v-=dist; e[i^1].v+=dist;
            }
            if (!ret) dep[now]=0; return ret;
        }
        inline int Dinic(int ret=0)
        {
            while (BFS()) memcpy(cur,head,t+1<<2),ret+=DFS(s,t,INF); return ret;
        }
    };
    class Segment_Tree
    {
        private:
            static const int N=1300005;
            struct segment
            {
                int ch[2];
            }node[N];
        public:
            #define lc(x) node[x].ch[0]
            #define rc(x) node[x].ch[1]
            #define TN CI l=1,CI r=n
            inline void insert(CI lst,int& now,CI pos,CI id,TN)
            {
                node[now=++tot]=node[lst]; if (lst) NF::addedge(now,lst,INF);
                if (l==r) return NF::addedge(now,id,INF); int mid=l+r>>1;
                if (pos<=mid) insert(lc(lst),lc(now),pos,id,l,mid);
                else insert(rc(lst),rc(now),pos,id,mid+1,r);
            }
            inline void link(CI now,CI beg,CI end,CI id,TN)
            {
                if (!now) return; if (beg<=l&&r<=end) return NF::addedge(id,now,INF); int mid=l+r>>1;
                if (beg<=mid) link(lc(now),beg,end,id,l,mid); if (end>mid) link(rc(now),beg,end,id,mid+1,r);
            }
            inline void relink(void)
            {
                for (RI i=n+1;i<=tot;++i)
                {
                    if (lc(i)) NF::addedge(i,lc(i),INF);
                    if (rc(i)) NF::addedge(i,rc(i),INF);
                }
            }
            #undef lc
            #undef rc
            #undef TN
    }SEG;
    inline void expand(CI now)
    {
        SEG.insert(lst,cur,a[now],now); lst=cur;
        for (RI i=head[now];i;i=e[i].nxt) expand(to);
    }
    inline void DFS1(CI now=1)
    {
        size[now]=1; int mx=0; for (RI i=head[now];i;i=e[i].nxt)
        DFS1(to),size[now]+=size[to],size[to]>mx&&(mx=size[to],son[now]=to);
    }
    inline void DFS2(CI now=1)
    {
        RI i; for (i=head[now];i;i=e[i].nxt) DFS2(to);
        lst=rt[son[now]]; SEG.insert(lst,cur,a[now],now); lst=cur;
        for (i=head[now];i;i=e[i].nxt) if (to!=son[now]) expand(to); rt[now]=lst;
    }
    #undef to
    int main()
    {
        RI i; for (scanf("%d%d",&n,&m),i=2;i<=n;++i) scanf("%d",&x),addedge(x,i);
        for (tot=n,i=1;i<=n;++i) scanf("%d",&a[i]); DFS1(); DFS2(); SEG.relink();
        for (NF::s=tot+m+1,NF::t=tot+m+2,i=1;i<=n;++i) NF::addedge(i,NF::t,1);
        for (i=1;i<=m;++i) scanf("%d%d%d%d",&l,&r,&x,&t),
        NF::addedge(NF::s,tot+i,t),SEG.link(rt[x],l,r,tot+i);
        return printf("%d",NF::Dinic()),0;
    }
    
  • 相关阅读:
    java导入导出下载Excel,xls文件(带下拉框)
    java操作poi生成excel.xlsx(设置下拉框)下载本地和前端下载
    layui文件上传中如何先判断后再弹出文件选择框
    下载excle文件之工具
    eclipse 配置JDK
    layer实现关闭弹出层刷新父界面功能详解
    兼容ie9以下支持媒体查询和html5
    layui学习地址
    MATLAB拟合正态分布
    Matlab文件操作
  • 原文地址:https://www.cnblogs.com/cjjsb/p/12244289.html
Copyright © 2011-2022 走看看