1. 程式人生 > 其它 >小w的矩陣前k大元素(mutiset+優先佇列貪心)

小w的矩陣前k大元素(mutiset+優先佇列貪心)

技術標籤:牛客練習

傳送門

設a陣列為[1,2,3,4,5]

b陣列為[2,2,3]

毫無疑問 ( 1 , 1 ) (1,1) (1,1)最小,次小呢 ? ? ?

我們把 ( 1 , 2 ) (1,2) (1,2) ( 2 , 1 ) (2,1) (2,1)入優先佇列,這兩個是可能最小的組合

每次優先佇列彈出來即可。

但是這麼進去會重複

考慮怎麼入隊不會重複

( 1 , 1 ) (1,1) (1,1)入隊

第一次擴充套件成 ( 1 , 2 ) (1,2) (1,2) ( 2 , 1 ) (2,1) (2,1)

後續只需要把 ( x , y ) (x,y) (x,y)擴充套件成 ( x + 1 , y ) (x+1,y)

(x+1,y)即可

那麼 y y y不需要管嗎??

不需要,因為 ( 1 , 2 ) (1,2) (1,2)在隊伍中,如果需要擴充套件 y y y會變成 ( 1 , 3 ) (1,3) (1,3)

這樣是最優的

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+10;
int n,m,q,a[maxn],b[maxn];
multiset<int>sa,sb;
struct node
{
	multiset<int>::iterator pa,pb;
	bool operator
< (const node &tmp ) const { return *pa+*pb>*tmp.pa+*tmp.pb; } }; int main() { cin >> n >> m >> q; for(int i=1;i<=n;i++) cin >> a[i]; for(int i=1;i<=m;i++) cin >> b[i]; int x = 1,y = 1; sa.insert( a[1] ); sb.insert( b[1] ); while( q-- ) { string w;
int k; cin >> w >> k; if( w[0]=='R' ) { int ny = min(m,y+k); for(int i=y+1;i<=ny;i++) sb.insert( b[i] ); y = ny; } else if( w[0]=='D' ) { int nx = min( n,x+k ); for(int i=x+1;i<=nx;i++) sa.insert( a[i] ); x = nx; } else { priority_queue<node>q; q.push({sa.begin(),sb.begin()}); for(int i=1;i<=k;i++) { node now = q.top(); q.pop(); printf("%d%c",*now.pa+*now.pb," \n"[i==k] ); if( now.pa==sa.begin() ) { auto w = now.pb; w++; if( w!=sb.end() ) q.push({now.pa,w}); } auto w = now.pa; w++; if( w!=sa.end() ) q.push({w,now.pb}); } } } return 0; }