1. 程式人生 > >BZOJ 3218 a + b Problem 網路流 可持久化線段樹優化建圖

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; }