zoukankan      html  css  js  c++  java
  • bzoj3681: Arietta

    Description

    Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中。
    但是她从未停止过和恋人 Velding 的书信往来。一天,她准备去探访他。
    对着窗外的阳光,临行前她再次弹起了琴。
    她的琴的发声十分特殊。
    让我们给一个形式化的定义吧。
    所有的 n 个音符形成一棵由音符 C ( 1 号节点) 构成的有根树,每一个音符有一个音高 Hi 。
    Arietta 有 m 个力度,第 i 个力度能弹出 Di 节点的子树中,音高在 [Li,Ri] 中的任意一个音符。
    为了乐曲的和谐,Arietta 最多会弹奏第 i 个力度 Ti 次。
    Arietta 想知道她最多能弹出多少个音符。

    Input

    输入共 m + 3 行。
    第一行两个整数 n, m ,意义如题目所述。
    第二行 n - 1 个整数 Pi ,表示节点 i ( i = 2 . . . n ) 的父亲节点的编号。
    第三行 n 个整数 Hi 。
    接下来的 m 行,每行四个整数 Li,Ri,D,Ti

    Output

    输出一个整数表示 Arietta 最多能弹奏多少音符。
    数据范围与约定
    对于 100% 的数据,1 ≤ n, m ≤ 10000 。
    对于所有数据,1 ≤ Hi , Ti , Pi ≤ n, 1 ≤ Li ≤ Ri ≤ n 。

    在树上做一次线段树合并(需要可持久化),得到每颗子树对应的音符集合,然后在线段树上查出对应的区间,优化建图跑最大流

    #include<cstdio>
    #include<algorithm>
    const int N=10007;
    int n,m,idp=0;
    int min(int a,int b){return a<b?a:b;}
    namespace mxf{
        struct edge{
            int to,nx,v;
        }e[N*150];
        int ep=2;
        int S,T,h[N*100],q[N*100],e0[N*100];
        void ae(int a,int b,int c){
            e[ep]=(edge){b,e0[a],c};e0[a]=ep++;
            e[ep]=(edge){a,e0[b],0};e0[b]=ep++;
        }
        bool bfs(){
            for(int i=1;i<=idp;++i)h[i]=0;
            int ql=0,qr=0;
            h[q[++qr]=S]=1;
            while(ql!=qr){
                int w=q[++ql];
                if(w==T)return 1;
                for(int i=e0[w];i;i=e[i].nx)if(e[i].v){
                    int u=e[i].to;
                    if(!h[u])h[q[++qr]=u]=h[w]+1;
                }
            }
            return 0;
        }
        int dfs(int w,int f){
            if(w==T)return f;
            int c,used=0;
            for(int i=e0[w];i;i=e[i].nx)if(e[i].v){
                int u=e[i].to;
                if(h[u]!=h[w]+1)continue;
                c=dfs(u,min(e[i].v,f-used));
                e[i].v-=c,e[i^1].v+=c,used+=c;
                if(f==used)return f;
            }
            h[w]=0;
            return used;
        }
        int maxflow(){
            int s=0;
            while(bfs())s+=dfs(S,n);
            return s;
        }
    }
    namespace sgt{
        int ch[N*100][2],rt[N];
        int build(int x,int L,int R){
            int w=++idp;
            if(L<R){
                int M=(L+R)>>1;
                if(x<=M)ch[w][0]=build(x,L,M);
                else ch[w][1]=build(x,M+1,R);
            }else mxf::ae(w,mxf::T,1);
            return w;
        }
        int get(int w,int l,int r,int L,int R){
            if(!w||l<=L&&R<=r)return w;
            int M=(L+R)>>1;
            if(r<=M||!ch[w][1])return get(ch[w][0],l,r,L,M);
            if(l>M||!ch[w][0])return get(ch[w][1],l,r,M+1,R);
            int u=++idp;
            ch[u][0]=get(ch[w][0],l,r,L,M);
            ch[u][1]=get(ch[w][1],l,r,M+1,R);
            return u;
        }
        int mg(int w1,int w2){
            if(w1&&w2){
                int w=++idp;
                ch[w][0]=mg(ch[w1][0],ch[w2][0]);
                ch[w][1]=mg(ch[w1][1],ch[w2][1]);
                return w;
            }
            return w1|w2;
        }
    }
    namespace tree{
        int es[N],enx[N],e0[N],h[N],hs[N],id[N][2],ep=2;
        void f1(int w){
            using namespace sgt;
            rt[w]=build(h[w],1,n);
            for(int i=e0[w];i;i=enx[i]){
                int u=es[i];
                f1(u);
                int ll=idp+1;
                rt[w]=mg(rt[w],rt[u]);
            }
        }
        void init(){
            for(int i=2,f;i<=n;++i){
                scanf("%d",&f);
                es[ep]=i;enx[ep]=e0[f];e0[f]=ep++;
            }
            for(int i=1;i<=n;++i)scanf("%d",h+i),hs[i]=h[i]*(n+1)+i;
            std::sort(hs+1,hs+n+1);
            for(int i=1;i<=n;++i)h[i]=std::lower_bound(hs+1,hs+n+1,h[i]*(n+1)+i)-hs;
            mxf::S=++idp;
            mxf::T=++idp;
            f1(1);
            for(int i=1;i<=m;++i){
                int l,r,d,t;
                scanf("%d%d%d%d",&l,&r,&d,&t);
                l=std::lower_bound(hs+1,hs+n+1,l*(n+1))-hs;
                r=std::upper_bound(hs+1,hs+n+1,(r+1)*(n+1))-hs-1;
                if(l<=r)mxf::ae(mxf::S,sgt::get(sgt::rt[d],l,r,1,n),t);
            }
            for(int i=3;i<=idp;++i)for(int d=0;d<2;++d)if(sgt::ch[i][d])mxf::ae(i,sgt::ch[i][d],n);
        }
    }
    int main(){
        scanf("%d%d",&n,&m);
        tree::init();
        printf("%d
    ",mxf::maxflow());
        return 0;
    }
  • 相关阅读:
    ubuntu c++ 关机 重启 挂起 API
    Java 并发 —— Java 标准库对并发的支持及 java.util.concurrent 包
    机器学习: Logistic Regression--python
    机器学习:朴素贝叶斯--python
    理解YOLOv2训练过程中输出参数含义
    darknet YOLO 编译使用GPU
    机器学习:决策树--python
    Xmodem通信协议实例
    MQTT协议笔记之连接和心跳
    Android实现推送方式解决方案
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6877221.html
Copyright © 2011-2022 走看看