topic
answer
When you see the title that says using network streaming to do A+B, your first reaction: This is a spoof blog
But this question is not A+B, it is a+b! (Case sensitive) , you will find something is wrong when you look at the title...
To get into the topic, we can first transform the problem:
First subtract everything , if the point is white, or if the point and the previous qualified points are all black, add it .
At this time, if you come up with a point S for white and T for black, take each point in the array on the graph, and define the point connected with S to be a white point, and the point connected to T with an edge is black,
This problem can be converted into a minimum cut problem.
The capacity of the edge connected from S is, and the capacity of the edge connected to T is (note the direction),
Then how to deal with this condition that requires a bunch of dots to be black?
You can create a virtual point (correspondingly, the point in the array corresponds to the point on the graph is a real point), and there is an edge with a capacity of connected to T, because according to requirements, if the edge is not cut, the virtual point is smoothly connected to T , Then the corresponding real points that must be black points must also have edges connected to T, so an edge connected virtual point with capacity INF can be established from each point. Because the capacity is a maximum value, this kind of edge cannot be included in the minimum cut and cannot be cut.
So far we ran a maximum flow Dinic to find the minimum cut, and then subtracted it from the sum of the edge capacity (except the INF edge), and it was solved soon?
However, the scope of this question is very unfriendly. According to the above mapping method, although the number of points is the level, the number of sides ;
The space is also not friendly, each test point is only 48MB, so I had to open int carefully. .
Therefore, we consider to reduce the number of edges by creating more virtual points. There are many specific methods, and there is more than one optical partition.
I will only introduce a very safe way to build a virtual chairman tree.
Specifically, after discretizing all the values of a, l, and r, a weighted line segment tree is established for all the prefixes (1≤j≤i) , and each interval on the line segment tree represents one in the figure. Imaginary point,
We define this as the dotted dotted interval (for convenience, the previously established with a capacity of edges connected to point T is the imaginary dotted conditions), then the tree on the interval (l, r) corresponding to the dotted section must It satisfies that all j corresponds to the real point on the graph directly or indirectly connected to the INF edge via other imaginary points in the interval.
This sentence is a bit long, but it can definitely be understood. In order to meet this condition, it is only necessary to connect the imaginary point corresponding to the interval between the left son and the right son to it, and the real point that satisfies the condition is connected to the leaf node,
Because and are equivalent, so every tree found (on ) corresponding to a plurality of virtual point range, in place of the original virtual point corresponding to the condition to be connected to a number of our established solid dot black dots, corresponding to a maximum because there is a Interval, at most new edges,
Then, for each tree B, we use the chairman tree to dynamically open points and create at most one point and edge each time , so the total number of points on the graph does not exceed , the total number of edges does not exceed (C and D are constants <10), and the space is not It will explode, and Dinic just happens to be able to run it.
Code
Added a few unnecessary optimizations, just understand it
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<climits>
#include<map>
#define ll long long
#define MAXN 400005 //边数点数大概是这个数量级
#define mst0(x) memset(x,0,sizeof(x))
#define INF 0x3f3f3f3f
using namespace std;
inline ll read(){
ll x=0;bool f=1;char s=getchar();
while((s<'0'||s>'9')&&s>0){if(s=='-')f^=1;s=getchar();}
while(s>='0'&&s<='9')x=(x<<1)+(x<<3)+s-'0',s=getchar();
return f?x:-x;
}
int n,IN,N;
int in[5005][6],SUM;
map<int,int>mp;
int root[MAXN],NN,XP,R;
int f[MAXN];
int d[MAXN],cur[MAXN];
struct edge{
int v,id;edge(){}
edge(int V,int I){v=V,id=I;}
};
vector<edge>G[MAXN];
queue<int>q;
bool ct[MAXN];
inline bool bfs(int S,int T){
for(int i=0,lm=min(XP,MAXN-5);i<=lm;i++)d[i]=-1;
q.push(S),d[S]=0;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v,a=G[u][i].id;
if(ct[v]&&f[a]>0&&d[v]<0)d[v]=d[u]+1,q.push(v);
}
}
return d[T]>=0;
}
inline int dfs(int x,int lim,int T){
if(x==T)return lim;
int res=lim;
for(int i=cur[x];i<G[x].size()&&res>0;i++){
cur[x]=i; //当前弧优化
int v=G[x][i].v,a=G[x][i].id;
if(ct[v]&&f[a]>0&&d[v]==d[x]+1){
int ad=dfs(v,min(res,f[a]),T);
f[a]-=ad,f[a^1]+=ad,res-=ad;
}
}
if(lim==res)d[x]=-1; //吔屎优化
return lim-res;
}
inline int dinic(int S,int T){
int res=0;
while(bfs(S,T)){
for(int i=0,lm=min(XP,MAXN-5);i<=lm;i++)cur[i]=0;
while(int ad=dfs(S,INF,T))res+=ad;
}
return res;
}
inline void addedge(int u,int v,int w){
if(w<INF)SUM+=w;
f[IN]=w,f[IN^1]=0;
G[u].push_back(edge(v,IN));
G[v].push_back(edge(u,IN^1));
IN+=2;
}
struct itn{
int ls,rs,id;
}t[MAXN];
inline void add(int x,int y,int l,int r,int u){
if(y>0)addedge(t[y].id,t[x].id,INF); //把先前点y的信息通过连边转过来
if(l==r){addedge(u,t[x].id,INF);return;}
int mid=(l+r)>>1;
if(in[u][0]<=mid){
t[x].rs=t[y].rs,t[x].ls=++NN,t[t[x].ls].id=++XP;//另一儿子无需连边,因为先前点y的信息已经转过来了
add(t[x].ls,t[y].ls,l,mid,u);
addedge(t[t[x].ls].id,t[x].id,INF);
}
else{
t[x].ls=t[y].ls,t[x].rs=++NN,t[t[x].rs].id=++XP;
add(t[x].rs,t[y].rs,mid+1,r,u);
addedge(t[t[x].rs].id,t[x].id,INF);
}
}
inline void sch(int x,int l,int r,int a,int b,int p){
if(x==0)return;
if(l==a&&r==b){addedge(t[x].id,p,INF);return;}
int mid=(l+r)>>1;
if(a<=mid)sch(t[x].ls,l,mid,a,min(mid,b),p);
if(b>mid)sch(t[x].rs,mid+1,r,max(a,mid+1),b,p);
}
inline void DFS(int x){
if(ct[x])return;ct[x]=1;
for(int i=0;i<G[x].size();i++)
if(G[x][i].id&1)DFS(G[x][i].v);
}
int main()
{
n=read(),N=(n<<1)+1;
for(int i=1;i<=n;i++){
for(int j=0;j<6;j++)in[i][j]=read();
SUM-=in[i][5];
mp[in[i][0]]=1,mp[in[i][3]]=1,mp[in[i][4]]=1;
}
map<int,int>::iterator it;
for(it=mp.begin();it!=mp.end();it++)it->second=++R;
for(int i=1;i<=n;i++)
in[i][0]=mp[in[i][0]],in[i][3]=mp[in[i][3]],in[i][4]=mp[in[i][4]];
XP=N;
for(int i=1;i<=n;i++){
addedge(0,i,in[i][2]+in[i][5]);
if(i==1)addedge(i,N,in[i][1]+in[i][5]);
else addedge(i,N,in[i][1]),
addedge(n+i,N,in[i][5]),addedge(i,n+i,INF);
sch(root[i-1],1,R,in[i][3],in[i][4],n+i);
if(i<n){
root[i]=++NN,t[root[i]].id=++XP;
add(root[i],root[i-1],1,R,i);
}
}
DFS(N); //把最终无法通向T的点删去,免跑
printf("%d\n",SUM-dinic(0,N));
return 0;
}