同步賽當場降智了,認為貪心是假的。。。。然後。。。。就寫了個暴力。。。。
開題一看,這不是模擬費用流嗎?
然而這個費用流並不顯然。。。。所以我當時放棄了t3部分分沒想到。
當然也希望這個題解能讓大家懂得什麼是真正的模擬費用流啦
大概是這麼一張圖……
正確性嘛……就是如果選下標不同的一對數的話必須走\(c -> d\) 這條路徑
那麼就保證了下標不同的數的對數會\(<= k - l\),那麼相同的就至少有\(l\)對了。
然後你按上述方法建圖,寫個費用流就可以拿到\(n = 150\)或者\(n = 2000\)的分了。
考慮一點一點的增加流量。
如果弧\(cd\)沒有流滿,我們就流弧\(cd\),因為它的選擇最「自由」,得到的答案也最優。
怎麼流最優呢?當然是當前沒有被選中的數中,a/b各取乙個max
當然如果我們選的數中有下標相等的,就不用佔據弧cd的流量了,這個需要注意。
在弧\(cd\)流滿之後,我們考慮增加其他弧的流量,也就是要組成新的一對下標相等的數
首先我們可以直接找乙個ab都沒被選過的下標,選出乙個\(a_i+b_i\) 最大的,反映到圖上就是把 \(s->a_i ->b_i ->t\) 流一遍
我們還可以給乙個已經選中的\(a\)找乙個\(b\)和它配對,然後你會發現這會使得\(c\)少一點流量,所以我們要給\(c\)一點流量,不然就不滿足流量平衡了
所以我們還得再找乙個最大的沒選過的\(a\)……
同樣的我也可以給乙個沒配過對的\(b\)配對,再補乙個最大的\(b\)上去……
反映到圖上,就是把一條\(a_i->c\)的流量撤回,改為從\(a_i->b_i->t\)
然後換乙個\(a_j\)補上,流一下\(s - >a_j - >c\)這條邊。
過程中如果發現弧cd可以不流滿,比如上述配對的過程中如果配出了兩對的話,我們就在剩下的a和b中分別選取乙個最大值,保證cd流滿。
這個就是一些人的貪心……在此處orz@_rqy提供的貪心思路……
不過我把它用費用流的角度解釋的話……它就是模擬費用流呀!
所以這個貪心(模擬費用流)是正確的!
然後我們發現我們只要求乙個最大值……用堆維護就可以了……
(**行數有點多,勿噴)
**裡有詳細注釋~~~
// f1,f2表示可以用來做配對操作的堆,h1,h2表示a、b兩個陣列中剩餘的數
// h3存的是a、b都沒選的那些i(也是堆)
#include #define ll long long
using namespace std;
inline int read()
inline void write(ll x)
inline void writeln(ll x)
const int n = 1000050;
ll ans;
int t,n,l,k,a[n],b[n],s[n]; // 0 -> () 1 -> (a) 2 -> (b) 3 -> (ab)
int id[n];
inline bool cmpa(int x,int y)
inline bool cmpb(int x,int y)
inline void work(int m)
struct nodea }tmp1;
struct nodeb }tmp2;
struct nodeab }t***;
priority_queueh1,f1;
priority_queueh2,f2;
priority_queueh3;
int main()
else if (s[i] == 1) tmp2.id = i,h2.push(tmp2),f2.push(tmp2);
else if (s[i] == 2) tmp1.id = i,h1.push(tmp1),f1.push(tmp1);
else ++now;
//a、b都選了的,我會計到now中去,now表示cd弧剩餘的流量。
} while (l--)
continue;
}v1 = v2 = v3 = c1 = c2 = 0;
if (!f2.empty())
if (!f1.empty())
if (!h3.empty()) //選一對a+b
vmx = max(v1,max(v2,v3));
ans += vmx;
if (v1 == v2 && v1 == vmx)
else
continue;
}if (v1 == vmx)
if (v2 == vmx)
if (v3 == vmx)
} writeln(ans);
} return 0;
}
NOI2019 序列(模擬費用流)
有兩個長度為n的序列,要求從每個序列中選k個,並且滿足至少有l個位置都被選,問總和最大是多少。1 leq l leq k leq n leq 2 10 5 首先,記錄當前考慮到的位置i,第乙個選的數量a,第二個選的數量b,都被選的數量c,可以做到 o n 4 卡常後能過 n leq 150 有40分...
NOI2019 序列(模擬費用流)
有兩個長度為n的序列,要求從每個序列中選k個,並且滿足至少有l個位置都被選,問總和最大是多少。1 leq l leq k leq n leq 2 10 5 首先,記錄當前考慮到的位置i,第乙個選的數量a,第二個選的數量b,都被選的數量c,可以做到 o n 4 卡常後能過 n leq 150 有40分...
NOI2019 序列 貪心,模擬費用流
傳送門 首先你需要知道網路流的建圖方法,偷一張圖 我開始沒有想到怎麼限制 l 個相同,我們何不先選出 k 對,然後把 k 對拆開調整兩邊的最 擇 新建兩個點 c,d 來給兩邊調整的空間 我們可以模擬這個網路流的運作過程 類似某些貪心的題,用堆來維護最大之類的 我們可以記錄 cd 可以通過的流量 fl...