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

来源:互联网 发布:苹果 知乎 编辑:程序博客网 时间:2024/06/03 19:42
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define N 200005#define INF 1000000000using 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;}
阅读全文
0 0
原创粉丝点击