题目链接:https://uoj.ac/problem/77
题目名称是吸引你点进来的。
从前有个 n n 个方格排成一行,从左至右依此编号为 1 , 2 , ⋯ , n 1 , 2 , ⋯ , n 。
有一天思考熊想给这 n n 个方格染上黑白两色。
第 i i 个方格上有 6 6 个属性:a i , b i , w i , l i , r i , p i a i , b i , w i , l i , r i , p i 。
如果方格 i i 染成黑色就会获得 b i b i 的好看度。
如果方格 i i 染成白色就会获得 w i w i 的好看度。
但是太多了黑色就不好看了。如果方格 i i 是黑色,并且存在一个 j j 使得 1 ≤ j < i 1 ≤ j < i 且 l i ≤ a j ≤ r i l i ≤ a j ≤ r i 且方格 j j 为白色,那么方格 i i 就被称为奇怪的方格。
如果方格 i i 是奇怪的方格,就会使总好看度减少 p i p i 。
也就是说对于一个染色方案,好看度为:
∑ 方 格 i 为 黑 色 b i + ∑ 方 格 i 为 白 色 w i − ∑ 方 格 i 为 奇 怪 的 方 格 p i ∑ 方格 i 为黑色 b i + ∑ 方格 i 为白色 w i − ∑ 方格 i 为奇怪的方格 p i
现在给你 n , a , b , w , l , r , p n , a , b , w , l , r , p ,问所有染色方案中最大的好看度是多少。
n ≤ 5000 , a , l , r ≤ 10 9 , v ≤ 2 × 10 5 , p ≤ 3 × 10 5 n ≤ 5000 , a , l , r ≤ 10 9 , v ≤ 2 × 10 5 , p ≤ 3 × 10 5 。
经典题。不过感觉十分缝合。
考虑没有黑白格子之间的限制怎么做。由于答案等价于所有格子黑白价值之和减去不选的颜色的价值之和,可以考虑网络流,源点连向每一个格子连一条流量为 b i b i 的边,每一个格子向汇点连一条流量为 w i w i 的边,然后跑最小割即可。
话说为什么不直接在黑格子和白格子权值中取个最大值啊。
现在有了黑白格子之间的限制,就把每一个点拆成两个点,第一个点依然先按上述方式连边,然后每一个点的一号点向二号点连一条流量为 p i p i 的边。二号点再向所有 j < i j < i 且 l i ≤ a j ≤ r i l i ≤ a j ≤ r i 的格子的一号点连边,边权为 + ∞ + ∞ 。
这样的话,一个格子要么切断黑边(选择白色);要么切断白边和一二号点之间的边(黑色,奇怪的方格);要么切断白边和所有二号点连向的点的白边(黑色,所影响的格子均为黑色)。显然是满足要求的。
但是这样建边的话,边数显然是 O ( n 2 ) O ( n 2 ) 的。由于每一个点是向一个区间的点连边,所以上线段树优化建图即可。
但是还有一个要求是每一个二号点只能向编号小于自己的点连边,所以还要套上一个可持久化。最终主席树 + 最小割即可。
时间复杂度 O ( n 3 log n ) O ( n 3 log n ) ,空间复杂度 O ( n log n ) O ( n log n ) 。
人傻常熟巨大,交了三发只过了一发。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=120010 ,Inf=1e9 ;
const ll InfLL=7e18 ;
int head[N],rt[N],a[N],b[N],w[N],p[N],L[N],R[N],cur[N],dep[N],pre[N];
int n,S,T,tot=1 ;
ll maxf,sumf,c[N];
struct edge
{
int next,to;
ll flow;
}e[N*20 ];
void add (int from,int to,ll flow)
{
e[++tot]=(edge){head[from],to,flow};
head[from]=tot;
e[++tot]=(edge){head[to],from,0 };
head[to]=tot;
}
struct SegTree
{
int tot,lc[N*4 ],rc[N*4 ];
int build (int l,int r)
{
int x=++tot;
if (l==r) return x;
int mid=(l+r)>>1 ;
lc[x]=build (l,mid); rc[x]=build (mid+1 ,r);
add (x+2 *n,lc[x]+2 *n,InfLL); add (x+2 *n,rc[x]+2 *n,InfLL);
return x;
}
void adde (int x,int l,int r,int ql,int qr,int u)
{
if (ql<=l && r<=qr)
{
add (u+n,x+2 *n,InfLL);
return ;
}
int mid=(l+r)>>1 ;
if (ql<=mid) adde (lc[x],l,mid,ql,qr,u);
if (qr>mid) adde (rc[x],mid+1 ,r,ql,qr,u);
}
int update (int now,int l,int r,int k,int u)
{
int x=++tot;
lc[x]=lc[now]; rc[x]=rc[now];
if (l==k && r==k)
{
add (x+2 *n,u,InfLL);
return x;
}
int mid=(l+r)>>1 ;
if (k<=mid) lc[x]=update (lc[now],l,mid,k,u);
else rc[x]=update (rc[now],mid+1 ,r,k,u);
add (x+2 *n,lc[x]+2 *n,InfLL); add (x+2 *n,rc[x]+2 *n,InfLL);
return x;
}
}seg;
bool bfs ()
{
memcpy (cur,head,sizeof (head));
memset (dep,0x3f3f3f3f ,sizeof (dep));
queue<int > q;
q.push (S); dep[S]=0 ;
while (q.size ())
{
int u=q.front (); q.pop ();
for (int i=head[u];~i;i=e[i].next)
{
int v=e[i].to;
if (e[i].flow && dep[v]>dep[u]+1 )
{
dep[v]=dep[u]+1 ; pre[u]=v;
q.push (v);
}
}
}
return dep[T]<Inf;
}
ll dfs (int x,ll flow)
{
if (x==T) return flow;
ll used=0 ,res;
for (int i=cur[x];~i;i=e[i].next)
{
int v=e[i].to; cur[x]=i;
if (e[i].flow && dep[v]==dep[x]+1 )
{
res=dfs (v,min (e[i].flow,flow-used));
used+=res;
e[i].flow-=res; e[i^1 ].flow+=res;
if (used==flow) return used;
}
}
return used;
}
void dinic ()
{
while (bfs ())
maxf+=dfs (S,InfLL);
}
int main ()
{
memset (head,-1 ,sizeof (head));
S=N-1 ; T=N-2 ;
scanf ("%d" ,&n);
for (int i=1 ;i<=n;i++)
{
scanf ("%d%d%d%d%d%d" ,&a[i],&b[i],&w[i],&L[i],&R[i],&p[i]);
add (S,i,b[i]); add (i,T,w[i]); add (i,i+n,p[i]);
sumf+=b[i]+w[i]; c[i]=1LL *a[i]*Inf+i;
}
sort (c+1 ,c+1 +n);
int cnt=unique (c+1 ,c+1 +n)-c-1 ;
c[++cnt]=InfLL;
rt[0 ]=seg.build (1 ,n);
for (int i=1 ;i<=n;i++)
{
a[i]=lower_bound (c+1 ,c+1 +cnt,1LL *Inf*a[i]+i)-c;
L[i]=lower_bound (c+1 ,c+1 +cnt,1LL *Inf*L[i])-c;
R[i]=lower_bound (c+1 ,c+1 +cnt,1LL *Inf*(R[i]+1 ))-c-1 ;
if (L[i]<=R[i]) seg.adde (rt[i-1 ],1 ,n,L[i],R[i],i);
rt[i]=seg.update (rt[i-1 ],1 ,n,a[i],i);
}
dinic ();
printf ("%lld\n" ,sumf-maxf);
return 0 ;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构