CF903G Yet Another Maxflow Problem

题目传送门

分析:
考虑把最大流转换成最小割来处理这个问题
考虑这个图的特性:
如果说我们要割去\(A_i\)\(A_{i+1}\)的边,那么对于\(j>i\),我们就没必要割去\(A_j\)\(A_{j+1}\)的边了
\(B\)同理,这样\(A\)\(B\)中我们只需要至多各自割掉一条边
因为有不割\(A\)\(B\),而多割一些中间的边代价更小的情况,由于处理起来比较麻烦,我们可以优化一下
\(A_0\)\(A_1\)\(B_n\)\(B_{n+1}\)连代价为0的边,求\(A_0\)\(B_{n+1}\)的最小割
这样\(A\)\(B\)中我们就可以各自割掉恰好一条边找到最小代价
假设割\(A_u\)\(A_{u+1}\)\(B_v\)\(B_{v+1}\),那么答案为

\(a_u+b_v+sum_{i\leq u,j>v}c_{i,j}\)

由于修改的只有\(a_u\),对于每个\(v\),后面的一部分的最小代价不收影响
按顺序枚举\(u\),加入必须割掉的边,用线段树维护取哪个\(v\)代价最小,即维护全局最小值
修改直接单点修改就好了
复杂度\(O(nlogn)\)

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<vector>

#define maxn 200005
#define pii pair<int,int>

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,m,q;
long long A[maxn],B[maxn],C[maxn];  
vector<pii >G[maxn];
long long mn[maxn<<2],lz[maxn<<2];

inline void build(int i,int l,int r)
{
	lz[i]=0;
	if(l==r){mn[i]=B[l];return;}
	int mid=(l+r)>>1;
	build(i<<1,l,mid),build(i<<1|1,mid+1,r);
	mn[i]=min(mn[i<<1],mn[i<<1|1]);
}
inline void pushdown(int i)
{if(lz[i]){mn[i<<1]+=lz[i],mn[i<<1|1]+=lz[i];lz[i<<1]+=lz[i],lz[i<<1|1]+=lz[i];lz[i]=0;}}

inline void update(int i,int l,int r,int ql,int qr,int w)
{
	if(ql>r||qr<l)return; 
	if(ql<=l&&r<=qr){mn[i]+=w,lz[i]+=w;return;}
	int mid=(l+r)>>1;
	pushdown(i);
	update(i<<1,l,mid,ql,qr,w),update(i<<1|1,mid+1,r,ql,qr,w);
	mn[i]=min(mn[i<<1],mn[i<<1|1]);
}

int main()
{
	n=getint(),m=getint(),q=getint();
	for(int i=2;i<=n;i++)A[i-1]=getint(),B[i]=getint();
	while(m--)
	{
		int u=getint(),v=getint(),w=getint();
		G[u].push_back(make_pair(v,w));
	}
	build(1,1,n); 
	for(int i=1;i<=n;i++)
	{
		for(int j=0;j<G[i].size();j++)update(1,1,n,1,G[i][j].first,G[i][j].second);
		C[i]=mn[1];
	}
	for(int i=1;i<=n;i++)B[i]=A[i]+C[i]; 
	build(1,1,n);
	printf("%lld\n",mn[1]);
	while(q--)
	{
		int p=getint(),x=getint(); 
		update(1,1,n,p,p,x-A[p]),A[p]=x; 
		printf("%lld\n",mn[1]);
	}
}

posted @ 2020-07-13 20:28  Izayoi_Doyo  阅读(103)  评论(0编辑  收藏  举报