ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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\n",mxf::maxflow());
    return 0;
}

 

 

 

posted on 2017-05-19 10:52  nul  阅读(208)  评论(0编辑  收藏  举报