我刚开始,我打眼一看:哇!网络流大水题,直接费用流板子,建边跟zz一样。结果看了一眼数据范围。。。gg,luogu上只能得30,直接建边就是n^2,1e5根本过不了。咋办,只能另谋出路。想不出来,看题解之后恍然大悟!!!woc,还有这样一句话:
保证所有 Ai各不相同,Bi也各不相同。
惊了,但是还是不会,然后就有这样一个显而易见的东西:a[i]只能和b[i - 1],b[i],b[i + 1]匹配,否则一定不是最优解。。。然后和dp一样的思路,每个状态由4个枚举转移过来,然后就好了。
然后20???分怎么还少了???然后尝试开longlong,30。。。后来发现中间有一个地方落了一个int,然后又加了一个无解的特判,60。。。这就很迷,最后,我突然发现我初始给附的初始值memset(f,127,sizeof(f))好像比1LL<<60小不少,然后改完才AC。。。
这个题犯了我近期所有犯过的错误。。。还是要仔细一点啊。
题干
Description 你有n 个整数Ai和n 个整数Bi。你需要把它们配对,即每个Ai恰好对应一 个Bp[i]。要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配 对。例如A={5,6,8},B={5,7,8},则最优配对方案是5配8, 6配5, 8配7,配对整数 的差的绝对值分别为2, 2, 1,和为5。注意,5配5,6配7,8配8是不允许的,因 为相同的数不许配对。 Input 第一行为一个正整数n,接下来是n 行,每行两个整数Ai和Bi,保证所有 Ai各不相同,Bi也各不相同。 Output 输出一个整数,即配对整数的差的绝对值之和的最小值。如果无法配对,输 出-1。 Sample Input 3 3 65 45 10 60 25 Sample Output 32 HINT 1 <= n <= 10^5,Ai和Bi均为1到10^6之间的整数。
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const long long INF = 1LL << 60; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } ll f[100005]; int n; ll a[100005],b[100005]; ll judge(int x,int y) { if(a[x] == b[y]) return INF; else return abs(a[x] - b[y]); } int main() { read(n); duke(i,1,n) { f[i] = INF; } duke(i,1,n) { read(a[i]); read(b[i]); } if(n == 1 && a[1] == b[1]) { printf("-1 "); return 0; } sort(a + 1,a + n + 1); sort(b + 1,b + n + 1); f[1] = judge(1,1); f[2] = min(judge(1,1) + judge(2,2),judge(1,2) + judge(2,1)); duke(i,3,n) { f[i] = min(f[i],f[i - 1] + judge(i,i)); f[i] = min(f[i],f[i - 2] + judge(i,i - 1) + judge(i - 1,i)); f[i] = min(f[i],f[i - 3] + judge(i,i - 2) + judge(i - 1,i - 1) + judge(i - 2,i)); f[i] = min(f[i],f[i - 3] + judge(i,i - 1) + judge(i - 1,i - 2) + judge(i - 2,i)); f[i] = min(f[i],f[i - 3] + judge(i,i - 2) + judge(i - 1,i) + judge(i - 2,i - 1)); } write(f[n]); return 0; }