• 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 。

    Sample Input

    5 2
    1 1 2 2
    5 3 2 4 1
    1 3 2 1
    3 5 1 4

    Sample Output

    4

    HINT

    第一个力度弹奏音符5,第二个力度弹奏音符1,2,4。


    数据范围与约定

    对于 100% 的数据,1 ≤ n, m ≤ 10000 。

    对于所有数据1<=Hi,Ti,Pi<=N,1<=Li<=Ri<=N

     
     
    我的内心是崩溃的。。。。。。。。。
    注意这两句话的区别:
    if(!x*y) return x+y;
    if(x*y==0) return x+y;
    看上去是一样的,但是。。。。。。
    !的运算级比*高。。。。。
    于是就*^*^*^*^^^^^^^*^^*^*^*^~*^~*^~*^~*~^*~^~*^~*~^*^~*^
     
     
    ——————————————————————————————————————————————————————
    题目是一个很明显的二分图匹配,但显然不能暴力连边,于是将一些数据结构嵌到网络流里。
    我开始想的是二维线段树,果断MLE了。
    正解是用主席树合并。。。。
    点数和边数都是nlogn
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,BufferSize,stdin);
            tail=(head=buffer)+l;
        }
        return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=10010;
    const int MAXN=200010;
    const int MAXM=1000010;
    struct Dinic {
        int n,m,s,t,first[MAXN],next[MAXM];
        struct Edge {int from,to,flow;}edges[MAXM];
        int q[MAXN],cur[MAXN],d[MAXN],vis[MAXN],clo;
        Dinic() {memset(first,-1,sizeof(first));}
        void AddEdge(int u,int v,int w) {
            edges[m]=(Edge){u,v,w};next[m]=first[u];first[u]=m++;
            edges[m]=(Edge){v,u,0};next[m]=first[v];first[v]=m++;
        }
        int BFS() {
            int l=1,r=0;q[++r]=s;vis[s]=++clo;
            while(l<=r) {
                int x=q[l++];cur[x]=first[x];
                for(int i=first[x];i!=-1;i=next[i]) {
                    Edge& e=edges[i];
                    if(e.flow&&vis[e.to]!=clo) {
                        vis[e.to]=clo;
                        d[e.to]=d[x]+1;
                        q[++r]=e.to;
                    }
                }
            }
            return vis[t]==clo;
        }
        int DFS(int x,int a) {
            if(x==t||!a) return a;
            int flow=0,f;
            for(int& i=cur[x];i!=-1;i=next[i]) {
                Edge& e=edges[i];
                if(d[e.to]==d[x]+1&&(f=DFS(e.to,min(a,e.flow)))) {
                    e.flow-=f;edges[i^1].flow+=f;
                    flow+=f;a-=f;if(!a) break;
                }
            }
            return flow;
        }
        int solve(int s,int t) {
            this->s=s;this->t=t;int flow=0;
            while(BFS()) flow+=DFS(s,1e9);
            return flow;
        }
    }sol;
    int n,m,first[maxn],next[maxn],to[maxn],e;
    void AddEdge(int u,int v) {
        to[++e]=v;next[e]=first[u];first[u]=e;
    }
    int s,t,root[MAXN],ls[MAXN],rs[MAXN],ToT;
    void insert(int v) {
        int l=1,r=n;ToT++;
        while(l<r) {
            int mid=l+r>>1;
            if(v<=mid) sol.AddEdge(ToT,ls[ToT]=ToT+1,1e9),r=mid;
            else sol.AddEdge(ToT,rs[ToT]=ToT+1,1e9),l=mid+1;
            ToT++;
        }
        sol.AddEdge(ToT,t,1);
    }
    int merge(int x,int y,int l,int r) {
        if(x*y==0) return x+y;
        int o=++ToT,mid=l+r>>1;
        if(l==r) sol.AddEdge(o,x,1e9),sol.AddEdge(o,y,1e9);
        else {
            sol.AddEdge(o,ls[o]=merge(ls[x],ls[y],l,mid),1e9);
            sol.AddEdge(o,rs[o]=merge(rs[x],rs[y],mid+1,r),1e9);
        }
        return o;
    }
    void dfs(int x) {ren dfs(to[i]),root[x]=merge(root[x],root[to[i]],1,n);}
    void query(int o,int l,int r,int ql,int qr) {
        if(!o) return;if(ql<=l&&r<=qr) sol.AddEdge(ToT,o,1e9);
        else {
            int mid=l+r>>1;
            if(ql<=mid) query(ls[o],l,mid,ql,qr);
            if(qr>mid) query(rs[o],mid+1,r,ql,qr);
        }
    }
    int main() {
        n=read();m=read();s=1;t=ToT=2;
        rep(i,2,n) AddEdge(read(),i);
        rep(i,1,n) root[i]=ToT+1,insert(read());
        dfs(1);while(m--) {
            int l=read(),r=read(),x=read(),k=read();
            sol.AddEdge(s,++ToT,k);query(root[x],1,n,l,r);
        }
        printf("%d
    ",sol.solve(s,t));
        return 0;
    }
    View Code
  • 相关阅读:
    网络通信2
    linux下使用shell脚本输出带颜色字体
    CentOS7 yum方式安装MySQL5.7
    Prometheus 基于文件的服务发现
    k8s容器探针
    kuberntes部署metallb LoadBalancer负载均衡
    [kubernetes]-namespace 处于Terminating状态的处理方法
    Kubernetes角色访问控制RBAC和权限规则
    k8s 关联pvc到特定的pv
    k8s创建kubeconfig文件
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4998975.html
Copyright © 2020-2023  润新知