1. 程式人生 > >【CF903G】Yet Another Maxflow Problem 線段樹

【CF903G】Yet Another Maxflow Problem 線段樹

pri soft string ace 題解 pda 容量 tro tor

【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;
}

【CF903G】Yet Another Maxflow Problem 線段樹