题意: 在一个环上有n个男生, n个女生, 现在要求每一个男生与女生配对, 求总代价最小。
题解:
如果2个男生到女生的路交叉了, 那么我们交换这2个男生的路, 总代价是一定会变得小的。
所以组合方式是线性的.
假设有3个男生 3个女生, 并且都已经排好序了。
搭配方式一共有3种。
1 <-> 1 2 <-> 2 3 <-> 3
1 <-> 2 2 <-> 3 3 <-> 1
1 <-> 3 2 <-> 1 3 <-> 2
因为不想要路径交叉, 所以就按照顺序给他们排序配对。
接下来就是顺时针走路和逆时针走的问题了。
先将B 扩展成 3B 减少讨论。
然后对于 a 来说 找到 a - 2/L 的位置 和 a + 1 的位置,
对 [a - 2/L, a] 来说 贡献都是 a-b, 对 [a + 1, a + 2/ L] 贡献都是 b-a.
然后对于每一个B也找到进入计算的时间, 出去的时间, 从负变成正的时间,然后搞一下差分就好了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 typedef pair<int,int> pll; 14 const int inf = 0x3f3f3f3f; 15 const LL INF = 0x3f3f3f3f3f3f3f3f; 16 const LL mod = (int)1e9+7; 17 const int N = 2e6; 18 LL a[N], b[N]; 19 int l[N], r[N], v[N], in[N], out[N]; 20 LL sum[N]; 21 struct FastIO { 22 static const int S = 1310720; 23 int wpos; 24 char wbuf[S]; 25 FastIO() : wpos(0) { } 26 inline int xchar() { 27 static char buf[S]; 28 static int len = 0, pos = 0; 29 if (pos == len) pos = 0, len = fread(buf, 1, S, stdin); 30 if (pos == len) return -1; 31 return buf[pos++]; 32 } 33 inline int xint() { 34 int c = xchar(), x = 0, s = 1; 35 while (c <= 32) c = xchar(); 36 if (c == '-') s = -1, c = xchar(); 37 for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0'; 38 return x * s; 39 } 40 ~FastIO() { 41 if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0; 42 } 43 } io; 44 inline int Find(int x, LL v){ 45 while(b[x] < v) x++; 46 return x; 47 } 48 LL n, L; 49 void in1(){ 50 n = io.xint(); 51 L = io.xint(); 52 for(int i = 1; i <= n; i++){ 53 a[i] = io.xint(); 54 a[i] += L; 55 } 56 for(int i = 1; i <= n; i++) 57 b[i] = io.xint(); 58 } 59 void in2(){ 60 scanf("%lld%lld", &n, &L); 61 for(int i = 1; i <= n; i++){ 62 scanf("%lld", &a[i]); 63 a[i] += L; 64 } 65 for(int i = 1; i <= n; i++) 66 scanf("%lld", &b[i]); 67 } 68 void solve(){ 69 in1(); 70 //in2(); 71 for(int i = 1;i <= 2*n; i++) 72 b[i+n] = b[i] + L; 73 for(int i = 1; i <= n; i++){ 74 l[i] = Find(l[i-1], a[i] - L/2); 75 r[i] = Find(r[i-1], a[i] + 1); 76 } 77 int lf = l[1]; 78 memset(sum, 0, sizeof(LL) *(n+1)); 79 for(int i = 1; i <= n; i++) sum[1] += a[i]; 80 for(int i = 1; i <= n; i++){ 81 int t = r[i] - lf + 1; 82 if(t - i >= 0) sum[t-i+1] -= 2 * a[i]; 83 else sum[1] -= a[i]; 84 } 85 v[0] = 1; 86 out[0] = 1; 87 int j = 1; 88 for(int i = lf; i <= n*3; i++, j++){ 89 if(j <= n) in[j] = 1; 90 else in[j] = in[j-1] + 1; 91 out[j] = out[j-1] + 1; 92 v[j] = v[j-1]; 93 while(v[j] <= n && a[v[j]] < b[i]) v[j]++; 94 if(in[j] > n) break; 95 } 96 for(int i = 1; i < j; i++){ 97 if(i <= n){ 98 v[i] = i - (v[i]-1) + 1; 99 if(v[i] < 1) v[i] = 1; 100 } 101 else { 102 if(v[i] == n+1) v[i] = in[i]; 103 else v[i] = in[i] + (n - v[i] + 1); 104 } 105 } 106 for(int i = 1, p = lf; i < j; i++, p++){ 107 sum[in[i]] -= b[p]; 108 if(out[i] <= v[i]) sum[out[i]] += b[p]; 109 else { 110 sum[v[i]] += 2 * b[p]; 111 sum[out[i]] -= b[p]; 112 } 113 } 114 LL ans = INF, tmp = 0;; 115 for(int i = 1; i <= n; i++){ 116 tmp += sum[i]; 117 ans = min(ans, tmp); 118 } 119 printf("%lld ", ans); 120 } 121 int main(){ 122 int t; 123 scanf("%d", &t); 124 while(t--){ 125 solve(); 126 } 127 return 0; 128 }