【CF903G】Yet Another Maxflow Problem 线段树

【CF903G】Yet Another Maxflow Problem

题意:一张图分为两部分,左边有n个点A,右边有m个点B,所有Ai->Ai+1有边,所有Bi->Bi+1有边,某些Ai->Bj有边,每条边都有一定的容量。

先要求你支持两种操作:

1.修改某条Ai->Ai+1的边的容量
2.询问从A1到Bm的最大流

n,m<=100000,流量<=10^9

题解:很有思维含量的题。

首先,我们把求最大流变成求最小割。容易发现,我们最多只会割一条Ai->Ai+1的边和一条Bi->Bi+1的边。

假设我们割掉了Ai->Ai+1的边,如果右边割掉的是Bj->Bj+1的边,那么我们还要割掉所有Ax->By的边(x<=i,y>j)。我们可以先预处理出对于每个i,最优的j是哪个。只需要从n到1枚举每个i,然后将从i连出去的边一条一条加进去,并用线段树维护区间加,全局最值即可。

由于每次只修改A的值,所以每个i选择的j是不变的,所以用堆维护一下最大值即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#define lson x<<1
#define rson x<<1|1
using namespace std;
const int maxn=200010;
typedef long long ll;
ll s[maxn<<2],tag[maxn<<2],f[maxn],A[maxn],B[maxn];
vector<int> C[maxn],D[maxn];
vector<int>::iterator ci,di;
int n,m,q;
struct heap
{
	priority_queue<ll,vector<ll>,greater<ll> > p1,p2;
	inline void erase(ll x) {p2.push(x);}
	inline void push(ll x) {p1.push(x);}
	inline ll top()
	{
		while(!p2.empty()&&p1.top()==p2.top())	p1.pop(),p2.pop();
		return p1.top();
	}
}p;
void build(int l,int r,int x)
{
	if(l==r)
	{
		s[x]=B[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,lson),build(mid+1,r,rson);
	s[x]=min(s[lson],s[rson]);
}
void updata(int l,int r,int x,int a,int b,int c)
{
	if(a<=l&&r<=b)
	{
		s[x]+=c,tag[x]+=c;
		return ;
	}
	if(tag[x])	s[lson]+=tag[x],s[rson]+=tag[x],tag[lson]+=tag[x],tag[rson]+=tag[x],tag[x]=0;
	int mid=(l+r)>>1;
	if(a<=mid)	updata(l,mid,lson,a,b,c);
	if(b>mid)	updata(mid+1,r,rson,a,b,c);
	s[x]=min(s[lson],s[rson]);
}
inline int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
	return ret*f;
}
int main()
{
	n=rd(),m=rd(),q=rd();
	int i,a;
	for(i=1;i<n;i++)	A[i]=rd(),B[i+1]=rd();
	for(i=1;i<=m;i++)	a=rd(),C[a].push_back(rd()),D[a].push_back(rd());
	build(1,n,1);
	for(i=1;i<=n;i++)
	{
		for(ci=C[i].begin(),di=D[i].begin();ci!=C[i].end();ci++,di++)	updata(1,n,1,1,*ci,*di);
		f[i]=s[1],p.push(A[i]+f[i]);
	}
	printf("%I64d\n",p.top());
	for(i=1;i<=q;i++)
	{
		a=rd(),p.erase(A[a]+f[a]),A[a]=rd(),p.push(A[a]+f[a]);
		printf("%I64d\n",p.top());
	}
	return 0;
}
posted @ 2017-12-24 09:48  CQzhangyu  阅读(482)  评论(0编辑  收藏  举报