版权声明:xgc原创文章,未经允许不得转载。 https://blog.csdn.net/xgc_woker/article/details/82911026
Description
有n个人和n匹马,第i个人对应第i匹马。第i个人能力值wi,第i匹马能力值hi,第i个人骑第j匹马的总能力值为wi*hj,整个军队的总能力值为∑wihj(一个人只能骑一匹马,一匹马只能被一个人骑)。有一个要求:每个人都不能骑自己对应的马。让你制定骑马方案,使得整个军队的总能力值最大。现在有q个操作,每次给出a,b,交换a和b对应的马。每次操作后你都需要输出最大的总能力值。
Sample Input
4 2
1 10 100 1000
3 7 2 5
2 4
2 4
Sample Output
5732
7532
有一个比较显然的结论是肯定是会和相邻的两个匹配。
然后你就可以用DP,DP的话只跟前两项有关系可以建立3*3的矩阵优化。
然后这个玩意可以用线段树优化???
点了一波技能树好吧。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
LL _min(LL x, LL y) {return x < y ? x : y;}
LL _max(LL x, LL y) {return x > y ? x : y;}
LL read() {
LL s = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
return s * f;
}
struct node {
LL x; int id;
} a[31000], b[31000];
int fac[31000], pos[31000];
bool ck(int x, int y) {return fac[a[x].id] != b[y].id;}
struct matrix {
LL m[3][3]; int l, r, lc, rc;
friend matrix operator * (matrix a, matrix b) {
matrix c;
memset(c.m, -31, sizeof(c.m));
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
for(int k = 0; k < 3; k++) {
c.m[i][j] = _max(c.m[i][j], a.m[i][k] + b.m[k][j]);
}
}
} return c;
}
void update(int x) {
memset(m, -31, sizeof(m));
if(ck(x, x)) m[0][0] = a[x].x * b[x].x;
if(x > 1 && ck(x, x - 1) && ck(x - 1, x)) m[1][0] = a[x].x * b[x - 1].x + a[x - 1].x * b[x].x;
if(x > 2 && ck(x, x - 2) && ck(x - 1, x) && ck(x - 2, x - 1)) m[2][0] = _max(m[2][0], a[x].x * b[x - 2].x + a[x - 1].x * b[x].x + a[x - 2].x * b[x - 1].x);
if(x > 2 && ck(x, x - 1) && ck(x - 2, x) && ck(x - 1, x - 2)) m[2][0] = _max(m[2][0], a[x].x * b[x - 1].x + a[x - 2].x * b[x].x + a[x - 1].x * b[x - 2].x);
if(x > 2 && ck(x, x - 2) && ck(x - 1, x - 1) && ck(x - 2, x)) m[2][0] = _max(m[2][0], a[x].x * b[x - 2].x + a[x - 1].x * b[x - 1].x + a[x - 2].x * b[x].x);
m[0][1] = m[1][2] = 0;
}
} t[61000]; int cnt;
bool cmp(node a, node b) {
if(a.x == b.x) return a.id < b.id;
return a.x < b.x;
}
void bt(int l, int r) {
int now = ++cnt;
t[now].l = l, t[now].r = r;
t[now].lc = t[now].rc = -1;
if(l < r) {
int mid = (l + r) / 2;
t[now].lc = cnt + 1; bt(l, mid);
t[now].rc = cnt + 1; bt(mid + 1, r);
}
}
void change(int now, int p) {
if(t[now].l == t[now].r) {t[now].update(t[now].l); return ;}
int mid = (t[now].l + t[now].r) / 2;
if(p <= mid) change(t[now].lc, p);
else change(t[now].rc, p);
int l = t[now].l, r = t[now].r, lc = t[now].lc, rc = t[now].rc;
t[now] = t[t[now].lc] * t[t[now].rc];
t[now].l = l, t[now].r = r, t[now].lc = lc, t[now].rc = rc;
}
int main() {
int n = read(), m = read();
for(int i = 1; i <= n; i++) a[i].x = read(), a[i].id = i;
for(int i = 1; i <= n; i++) b[i].x = read(), b[i].id = i;
sort(a + 1, a + n + 1, cmp), sort(b + 1, b + n + 1, cmp);
for(int i = 1; i <= n; i++) fac[i] = i;
bt(1, n);
for(int i = 1; i <= n; i++) pos[a[i].id] = i, change(1, i);
for(int i = 1; i <= m; i++) {
int x = read(), y = read();
swap(fac[x], fac[y]);
for(int i = pos[x]; i <= _min(n, pos[x] + 2); i++) change(1, i);
for(int i = pos[y]; i <= _min(n, pos[y] + 2); i++) change(1, i);
printf("%lld\n", t[1].m[0][0]);
}
return 0;
}