Atcoder D - 3N Numbers(优先队列+dp)
题目链接:http://abc062.contest.atcoder.jp/tasks/arc074_b
题意:给出3*n个数要求去掉n个数使得剩下的前n个数-后n个数的差最大。
题解:显然是一道如果数据小直接dpf[i][j]表示前i个取j个最大是多少,dpe[i][j]后i个取j个最小是多少。
显然转移也是很明显的dpf[i][j]=max(dpf[i][j],dpf[i-1][j-1]+a[i]),dpe[i][j]=min(dpe[i][j],dpe[i+1][j-1]+a[i]);
但是数据有100000不能这么存但是依旧是dp
dpf[i]表示前i个取n个最大是多少,dpe[i]表示后i个取n个最小是多少,然后用优先队列维护一下。
#include <iostream> #include <cstring> #include <queue> #include <cstdio> using namespace std; const int M = 3e5 + 10; typedef long long ll; int a[M]; struct cmp1 { int x; cmp1(int x):x(x) {} bool operator < (const cmp1 &a) const { return x > a.x; } }; struct cmp2 { int x; cmp2(int x):x(x) {} bool operator < (const cmp2 &a) const { return x < a.x; } }; ll dpf[M] , dpe[M]; int main() { int n; scanf("%d" , &n); for(int i = 1 ; i <= 3 * n ; i++) { scanf("%d" , &a[i]); } priority_queue<cmp1> st; memset(dpf , 0 , sizeof(dpf)); memset(dpe , 0 , sizeof(dpe)); for(int i = 1 ; i <= n ; i++) { st.push(cmp1(a[i])); dpf[n] += (ll)a[i]; } for(int i = n + 1 ; i <= 2 * n ; i++) { int gg = st.top().x; if(gg < a[i]) {st.pop() , st.push(cmp1(a[i])) , dpf[i] = dpf[i - 1] - (ll)gg + (ll)a[i];} else dpf[i] = dpf[i - 1]; } priority_queue<cmp2> ed; for(int i = 2 * n + 1 ; i <= 3 * n ; i++) { ed.push(cmp2(a[i])); dpe[2 * n + 1] += (ll)a[i]; } for(int i = 2 * n ; i >= n ; i--) { int gg = ed.top().x; if(gg > a[i]) {ed.pop() , ed.push(cmp2(a[i])) , dpe[i] = dpe[i + 1] - (ll)gg + (ll)a[i];} else dpe[i] = dpe[i + 1]; } ll ans = -10000000000000000; for(int i = n ; i <= 2 * n ; i++) { ans = max(ans , dpf[i] - dpe[i + 1]); } printf("%lld\n" , ans); return 0; }