【CF903G】Yet Another Maxflow Problem 線段樹
阿新 • • 發佈:2017-12-24
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 線段樹