#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;
}
BZOJ 3218 a + b Problem 网络流 可持久化线段树优化建图
最新推荐文章于 2025-02-18 18:32:22 发布