日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[CF903G]Yet Another Maxflow Problem

發布時間:2023/12/9 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CF903G]Yet Another Maxflow Problem 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

[CF903G]Yet Another Maxflow Problem

題目大意:

\(A\)類點和\(B\)類點各\(n(n\le2\times10^5)\)個,所有\(A_i\)\(A_{i+1}\)有一條權值為\(a_i\)的有向邊,所有\(B_i\)\(B_{i+1}\)有一條權值為\(b_i\)的有向邊,另有\(m(m\le2\times10^5)\)條從\(A_x\)\(B_y\)的權值為有向邊。連續\(q(q\le2\times10^5)\)次操作將\(A_{v_i}\)\(A_{v_i+1}\)之間的邊的權值改為\(w_i\)。問每次修改完畢后的從\(A_1\)\(B_n\)的最大流。

思路:

根據最大流-最小割定理,題目所求相當于每次修改完畢后的最小割。定義\(A\)類點間的邊為\(A\)類邊,\(B\)類點間的邊為\(B\)類邊,\(AB\)類點間的邊為\(C\)類邊。假設兩類邊各\(n-1\)條之外還分別有一個邊權為\(0\)的邊,那么每次的最小割一定恰好包含一個\(A\)類邊、一個\(B\)類邊和若干\(C\)類邊。由于\(B\)類邊和\(C\)類邊都不會被修改,則對于同一個\(A\)類邊,對應的最優的\(B\)類邊是固定的。方便起見,下文將\(B_i\)\(B_{i+1}\)的邊記作\(b_{i+1}\),不同于題面描述。

考慮預處理每個\(A\)類邊對應的最優\(B\)類邊。不難發現,若我們選擇了\(a_i\)\(b_j\)兩條邊,要使得\(A_1\)\(B_n\)不連通,則我們還需要割去所有連接\(A_x,B_y(x\le i,y\ge j)\)\(C\)類邊,而這也是選擇\(a_i\)\(b_j\)后的最小割。反過來說,連接\(A_x,B_y\)\(C\)類邊會對\(a_i,b_j(x\le i,y\ge j)\)的選擇產生影響。因此我們可以\(1\sim n\)枚舉每個\(a_i\),用線段樹維護對應每個\(b_j\)所需要的最小割的大小。首先將所有\(b_j\)加入到線段樹中,對于當前枚舉到的\(a_i\),枚舉從\(A_i\)出發的所有\(C\)類邊,若對應的點為\(B_j\),權值為\(w\),將區間\([1,j]\)加上\(w\),表示對于\(a_i\)\(a_i\)以后的\(A\)類邊,若還要考慮\(b_j\)\(b_j\)以前的\(B\)類邊作為對應邊,一定要割去這條\(C\)類邊。而每次插入后線段樹最小元素就是對應當前\(a_i\),由一個\(B\)類邊和若干\(C\)類邊組成的、能與\(a_i\)構成割的邊權和,記這一邊權和為\(sum\),則選擇\(a_i\)時的最小割為\(sum+a_i\),記作\(c_i\)

考慮修改操作,由于\(a_i\)對應的\(B\)類邊和\(C\)類邊已經確定,每次修改時\(a_i\)的變化也就是\(c_i\)的變化。用一些數據結構維護所有\(c_i\)的最小值即可。時間復雜度\(\mathcal O((m+q)\log n)\)

源代碼:

#include<cstdio> #include<cctype> #include<vector> using int64=long long; inline int getint() {register char ch;while(!isdigit(ch=getchar()));register int x=ch^'0';while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');return x; } constexpr int N=2e5+1; int64 a[N],b[N],c[N]; using Edge=std::pair<int,int>; std::vector<Edge> e[N]; class SegmentTree {#define _left <<1#define _right <<1|1private:int64 val[N<<2],tag[N<<2];void push_up(const int &p) {val[p]=std::min(val[p _left],val[p _right]);}void push_down(const int &p) {if(!tag[p]) return;val[p _left]+=tag[p];val[p _right]+=tag[p];tag[p _left]+=tag[p];tag[p _right]+=tag[p];tag[p]=0;}public:void build(const int &p,const int &b,const int &e,const int64 arr[]) {tag[p]=0;if(b==e) {val[p]=arr[b];return;}const int mid=(b+e)>>1;build(p _left,b,mid,arr);build(p _right,mid+1,e,arr);push_up(p);}void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int64 &v) {if(b==l&&e==r) {val[p]+=v;tag[p]+=v;return;}push_down(p);const int mid=(b+e)>>1;if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),v);if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,v);push_up(p);}int64 query() const {return val[1];}#undef _left#undef _right }; SegmentTree t; int main() {const int n=getint(),m=getint(),q=getint();for(register int i=1;i<n;i++) {a[i]=getint(),b[i+1]=getint();}t.build(1,1,n,b);for(register int i=0;i<m;i++) {const int u=getint(),v=getint(),w=getint();e[u].push_back({v,w});}for(register int x=1;x<=n;x++) {for(register auto &j:e[x]) {const int &y=j.first,&w=j.second;t.modify(1,1,n,1,y,w);}c[x]=t.query()+a[x];}t.build(1,1,n,c);printf("%lld\n",t.query());for(register int i=0;i<q;i++) {const int x=getint(),v=getint();t.modify(1,1,n,x,x,v-a[x]);a[x]=v;printf("%lld\n",t.query());}return 0; }

轉載于:https://www.cnblogs.com/skylee03/p/9087266.html

總結

以上是生活随笔為你收集整理的[CF903G]Yet Another Maxflow Problem的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。