BZOJ 3218 a + b Problem 网络流 可持久化线段树优化建图

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 200005
#define INF 1000000000
using namespace std;
int n;
namespace NetworkFlow {
    struct Edge {
        int to,nxt,cap;
        Edge() {}
        Edge(int _to,int _nxt,int _cap):
            to(_to),nxt(_nxt),cap(_cap) {}
    }e[N*5];
    int tot,S,T,fir[N],cur[N],d[N];
    void Add_Edge(int from,int to,int cap) {
        e[++tot]=Edge(to,fir[from],cap), fir[from]=tot;
        e[++tot]=Edge(from,fir[to],0), fir[to]=tot;
        return ;
    }
    bool bfs() {
        queue<int> q;
        for(int i=S;i<=T;++i) d[i]=-1;
        d[S]=0, q.push(S);
        while(!q.empty()) {
            int x=q.front(); q.pop();
            for(int i=fir[x];~i;i=e[i].nxt) {
                if(!e[i].cap || d[e[i].to]!=-1) continue;
                d[e[i].to]=d[x]+1;
                if(e[i].to==T) return true;
                q.push(e[i].to);
            }
        }
        return false;
    }
    int dfs(int x,int now) {
        if(!now || x==T) return now;
        int f,flow=0;
        for(int& i=cur[x];~i;i=e[i].nxt) {
            if(d[e[i].to]!=d[x]+1) continue;
            f=dfs(e[i].to,min(e[i].cap,now));
            if(!f) continue;
            e[i].cap-=f, e[i^1].cap+=f;
            now-=f, flow+=f;
            if(!now) break;
        }
        return flow;
    }
    int Dinic() {
        int maxflow=0;
        while(bfs()) {
            for(int i=S;i<=T;++i) cur[i]=fir[i];
            maxflow+=dfs(S,INF);
        }
        return maxflow;
    }
    void init() {
        memset(fir,-1,sizeof fir), tot=-1;
        S=0, T=N-1;
        return ;
    }
}
namespace SegmentTree {
    int tot=0;
    struct Node {
        Node* ch[2];
        int l,r,ord;
        Node(Node* tmp=NULL) {
            if(tmp!=NULL) {
                l=tmp->l, r=tmp->r;
                ch[0]=tmp->ch[0];
                ch[1]=tmp->ch[1];
            }
        }
        Node(int _l,int _r):l(_l),r(_r) {
            ch[0]=ch[1]=NULL;
        }
        void* operator new(size_t) {
            static Node *mempool,*C;
            if(mempool==C) mempool=(C=new Node[N])+N;
            ++tot;
            return C++;
        }
    }*root[N];
    void init(Node*& o,int l,int r) {
        o=new Node(l,r);
        o->ord=tot;
        if(l==r) return ;
        int mid=l+r>>1;
        init(o->ch[0],l,mid), init(o->ch[1],mid+1,r);
        using NetworkFlow::Add_Edge;
        Add_Edge(n*2+o->ch[0]->ord,n*2+o->ord,INF);
        Add_Edge(n*2+o->ch[1]->ord,n*2+o->ord,INF);
        return ;
    }
    void build(int m) {
        init(root[0],1,m);
        return ;
    }
    void change(Node*& o,int pos,int ord) {
        using NetworkFlow::Add_Edge;
        Node* tmp=o;
        o=new Node(tmp);
        o->ord=tot;
        Add_Edge(n*2+tmp->ord,n*2+o->ord,INF);
        if(o->l==o->r) {
            Add_Edge(ord,n*2+o->ord,INF);
            return ;
        }
        int mid=o->l+o->r>>1,dir=pos<=mid?0:1;
        change(o->ch[dir],pos,ord);
        Add_Edge(n*2+o->ch[dir]->ord,n*2+o->ord,INF);
        return ;
    }
    void query(Node* o,int l,int r,int ord) {
        if(o->l==l && o->r==r) {
            NetworkFlow::Add_Edge(n*2+o->ord,ord+n,INF);
            return ;
        }
        int mid=o->l+o->r>>1;
        if(r<=mid) query(o->ch[0],l,r,ord);
        else if(l>mid) query(o->ch[1],l,r,ord);
        else query(o->ch[0],l,mid,ord), query(o->ch[1],mid+1,r,ord);
        return ;
    }
}
long long sum;
int top,c[N*3];
struct Data {
    int a,b,w,l,r,p;
    void scan(int ord) {
        using NetworkFlow::Add_Edge;
        using NetworkFlow::S; using NetworkFlow::T;
        scanf("%d%d%d%d%d%d",&a,&b,&w,&l,&r,&p);
        c[++top]=a, c[++top]=l, c[++top]=r;
        Add_Edge(S,ord,w), Add_Edge(ord,T,b), Add_Edge(ord+n,ord,p);
        sum+=w+b;
        return ;
    }
    void adjust() {
        a=lower_bound(c+1,c+top+1,a)-c;
        l=lower_bound(c+1,c+top+1,l)-c;
        r=lower_bound(c+1,c+top+1,r)-c;
        return ;
    }
    bool judge(int x) {
        return l<=x && x<=r;
    }
    void build(int ord) {
        using SegmentTree::root;
        using SegmentTree::change;
        using SegmentTree::query;
        query(root[ord-1],l,r,ord);
        root[ord]=root[ord-1];
        change(root[ord],a,ord);
        return ;
    }
}d[N];
int main() {
    scanf("%d",&n);
    NetworkFlow::init();
    for(int i=1;i<=n;++i) d[i].scan(i);
    sort(c+1,c+top+1);
    top=unique(c+1,c+top+1)-c-1;
    for(int i=1;i<=n;++i) d[i].adjust();
    SegmentTree::build(top);
    for(int i=1;i<=n;++i) d[i].build(i);
    printf("%lld\n",sum-NetworkFlow::Dinic());
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值