zoukankan      html  css  js  c++  java
  • bzoj3681 Arietta

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3681

    【题解】

    这题和bzoj3218很像,都是有二维限制关系的网络流。

    先考虑了bzoj3218是用主席树来建图然后网络流,感觉这题也能这样做(在dfs序上,主席树建图)

    后来发现这样好像不兹磁区间减法啊

    然后发现可以线段树合并来做,这样就很兹磁了。

    加边的时候(u, v, flow)反向边也加成了(v, u, flow)坑了好久。。。

    时间复杂度能过(逃)

    还有一个坑待解决

    如果bzoj3218加强成不仅有权值区间$[l_i,r_i]$,还有下标区间$[L_i,R_i]$,其中$L_i leq R_i leq i$,那么要怎么解决啊?

    主席树好像就不行了啊qwq 本题因为有树结构、子树查询所以恰巧比较兹磁线段树合并来维护。

    立个flag:这坑noi前解决不了。

    upd: 好像一发完博客我就会了。。用树套树就行了(逃

    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int N = 1e4 + 10, M = 1e6 + 5;
    const int mod = 1e9+7, inf = 1e9;
    
    int n, m, par[N], w[N], offset, all;
    int head[N], nxt[N], to[N], tot = 0;
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    
    int S, T;
    namespace MF {
        int head[M], nxt[M], to[M], flow[M], tot = 1; 
        inline void add(int u, int v, int fl) {
            ++tot; nxt[tot] = head[u]; head[u] = tot;
            to[tot] = v, flow[tot] = fl;
        }
        inline void adde(int u, int v, int fl) {
            add(u, v, fl), add(v, u, 0);
        }
        int c[M], cur[M]; queue<int> q;    
        inline bool bfs() {
            while(!q.empty()) q.pop();
            for (int i=1; i<=all; ++i) c[i] = -1;
            c[S] = 0; q.push(S);
            while(!q.empty()) {
                int top = q.front(); q.pop();
                for (int i=head[top]; i; i=nxt[i]) {
                    if(c[to[i]] != -1 || !flow[i]) continue;
                    c[to[i]] = c[top] + 1;
                    q.push(to[i]); 
                    if(to[i] == T) return 1;
                }
            }
            return 0;
        }
        inline int dfs(int x, int low) {
            if(x == T) return low;
            int r = low, fl;
            for (int i=cur[x]; i; i=nxt[i]) {
                if(c[to[i]] != c[x]+1 || !flow[i]) continue;
                fl = dfs(to[i], min(r, flow[i])); 
                r -= fl, flow[i] -= fl, flow[i^1] += fl;
                if(flow[i] > 0) cur[x] = i; 
                if(!r) return low;
            }
            if(low == r) c[x] = -1;
            return low-r;
        }
        inline int main() {
            int ans = 0;
            while(bfs()) {
                for (int i=1; i<=all; ++i) cur[i] = head[i];
                ans += dfs(S, inf);
            }
            return ans;
        } 
    }
    
    int rt[N]; 
    struct SMT {
        int ch[M][2], siz;
        inline void set() {siz = 0;} 
        inline int newnode() {return ++siz;}
        inline int build(int l, int r, int ps, int p) {
            int x = newnode();
    //        cout << x + offset << "   [" << l << "," << r <<"]
    "; 
            if(l == r) {
                MF :: adde(p, x + offset, inf);
                return x;
            }
            int mid = l+r>>1;
            if(ps <= mid) ch[x][0] = build(l, mid, ps, p);
            else ch[x][1] = build(mid+1, r, ps, p);
            if(ch[x][0]) MF :: adde(ch[x][0] + offset, x + offset, inf);
            if(ch[x][1]) MF :: adde(ch[x][1] + offset, x + offset, inf);
            return x;
        }
        inline int merge(int a, int b, int l, int r) {
            if(!a || !b) return a + b;
            int x = newnode(); 
    //        cout << x + offset << " - [" << l << "," << r <<"]
    "; 
            if(l == r) {
                MF :: adde(a + offset, x + offset, inf);
                MF :: adde(b + offset, x + offset, inf);
                return x;
            }
            int mid = l+r>>1;
            ch[x][0] = merge(ch[a][0], ch[b][0], l, mid); 
            ch[x][1] = merge(ch[a][1], ch[b][1], mid+1, r);        
            if(ch[x][0]) MF :: adde(ch[x][0] + offset, x + offset, inf);
            if(ch[x][1]) MF :: adde(ch[x][1] + offset, x + offset, inf);
            return x;
        }
        inline void link(int x, int l, int r, int L, int R, int p) {
            if(!x) return ;
            if(L <= l && r <= R) {
                MF :: adde(x + offset, p, inf);
                return ;
            }
            int mid = l+r>>1;
            if(L <= mid) link(ch[x][0], l, mid, L, R, p);
            if(R > mid) link(ch[x][1], mid+1, r, L, R, p);
        }
    }t;
    
    inline void dfs(int x) {
        rt[x] = t.build(1, n, w[x], x);
        for (int i=head[x]; i; i=nxt[i]) {
            dfs(to[i]);
            rt[x] = t.merge(rt[x], rt[to[i]], 1, n);
        }
    }
    
    int main() {
        cin >> n >> m; t.set(); 
        S = n+m+1, offset = T = n+m+2;
        for (int i=2; i<=n; ++i) {
            scanf("%d", par+i);
            add(par[i], i);
        }
        for (int i=1; i<=n; ++i) {
            MF :: adde(S, i, 1);
            scanf("%d", w+i);
        }
        dfs(1);
        for (int i=1, L, R, D, times; i<=m; ++i) {
            scanf("%d%d%d%d", &L, &R, &D, &times); 
             t.link(rt[D], 1, n, L, R, i+n);
             MF :: adde(i+n, T, times); 
        }
        all = offset + t.siz;
        cout << MF::main(); 
        return 0;
    }
    /*
    5 2
    1 1 2 2
    5 3 2 4 1
    1 3 2 1
    3 5 1 4
    */
    View Code
  • 相关阅读:
    Ubuntu安装搜狗sougou输入法
    gradle windows 环境变量
    Gradle 使用Maven本地缓存
    Java 命令后台运行jar包
    spark 2.1.0 集群安装
    hadoop 2.7.3 集群安装
    springboot + shiro + cas4.2.7 实战
    cas4.2以下取消https
    cas4.2.7 取消https
    springboot 中使用websocket简单例子
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3681.html
Copyright © 2011-2022 走看看