tema
respuesta
Cuando vea el título que dice usar la transmisión en red para hacer A + B, su primera reacción: este es un blog falso
Pero esta pregunta no es A + B, ¡es a + b! (Distingue entre mayúsculas y minúsculas) , encontrará que algo está mal cuando mire el título ...
Para entrar en el tema, primero podemos transformar el problema:
Primero reste todo , si el punto es blanco, o si el punto y los puntos calificados anteriores son todos negros, sume .
En este momento, si encuentra un punto S que representa el blanco y T que representa el negro, tome cada punto de la matriz en el gráfico y defina el punto conectado a S con un borde como un punto blanco, y el punto conectado a T con un borde es negro,
Este problema se puede convertir en un problema de corte mínimo.
La capacidad del borde conectado desde S es, y la capacidad del borde conectado a T es (observe la dirección),
Entonces, ¿cómo lidiar con esta condición que requiere que un montón de puntos sean negros?
Puede crear un punto virtual (en consecuencia, el punto en la matriz corresponde al punto en el gráfico es un punto real), y hay un borde con una capacidad de conectado a T, porque de acuerdo con los requisitos, si el borde no es corte, el punto virtual se conecta suavemente a T, luego los puntos reales correspondientes que deben ser puntos negros también deben tener bordes conectados a T, por lo que se puede establecer un punto virtual conectado por borde con capacidad INF desde cada punto. Debido a que la capacidad es un valor máximo, este tipo de borde no se puede incluir en el corte mínimo y no se puede cortar.
En este punto, ejecutamos un Dinic de flujo máximo para encontrar el corte mínimo, y luego lo restamos de la suma de las capacidades de los bordes (excepto el borde INF) ¿Pronto se resolvió?
Sin embargo, el alcance de esta pregunta es muy poco amigable Según el método de mapeo anterior, aunque el número de puntos es el nivel, el número de lados ;
El espacio tampoco es amigable, cada punto de prueba tiene solo 48 MB, por lo que tuve que abrir int con cuidado. .
Por lo tanto, consideramos reducir el número de aristas creando más puntos virtuales Hay muchos métodos específicos y hay más de una partición óptica.
Solo presentaré una forma muy segura de crear un árbol de presidente virtual.
Específicamente, después de discretizar todos los valores de a, lyr , se establece un árbol de segmento de línea ponderado para todos los prefijos (1≤j≤i) , y cada intervalo en el árbol de segmento de línea representa uno en la figura. Punto imaginario
Definimos esto como el intervalo de puntos (por conveniencia, lo previamente establecido con una capacidad de aristas conectadas al punto T son las condiciones imaginarias de puntos), entonces el árbol en el intervalo (l, r) correspondiente a la sección de puntos debe Satisfacer que todo j corresponde al punto real en el gráfico conectado directa o indirectamente al borde INF a través de otros puntos imaginarios en el intervalo.
Esta oración es un poco larga, pero definitivamente se puede entender. Para cumplir esta condición, solo es necesario conectar el punto imaginario correspondiente al intervalo entre el hijo izquierdo y el hijo derecho a él, y el punto real que satisface la condición se conecta al nodo hoja,
Porque y son equivalentes, por lo que cada árbol encontrado (encendido ) corresponde a una pluralidad de rango de puntos virtuales, en lugar del punto virtual original correspondiente a la condición para estar conectado a un número de nuestros puntos negros de puntos sólidos establecidos, correspondientes a un máximo porque hay un intervalo, en la mayoría de los bordes nuevos ,
Luego, para cada árbol B, usamos el árbol del presidente para abrir puntos dinámicamente y crear como máximo un punto y un borde cada vez , de modo que el número total de puntos en el gráfico no exceda , el número total de bordes no exceda (C y D son constantes <10), y el espacio no lo es. Explotará, y resulta que Dinic puede ejecutarlo.
Código
Se agregaron algunas optimizaciones innecesarias, solo entiéndelo
#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;
}