洛谷P1966 [NOIP2013提高组Day1T2]火柴排队
P1966 火柴排队
题目描述
涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相同, 两列火柴之间的距离定义为: ∑(ai-bi)^2
其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
输入输出格式
输入格式:输入文件为 match.in。
共三行,第一行包含一个整数 n,表示每盒中火柴的数目。
第二行有 n 个整数,每两个整数之间用一个空格隔开,表示第一列火柴的高度。
第三行有 n 个整数,每两个整数之间用一个空格隔开,表示第二列火柴的高度。
输出格式:输出文件为 match.out。
输出共一行,包含一个整数,表示最少交换次数对 99,999,997 取模的结果。
输入输出样例
输入样例#1:
4 2 3 1 4 3 2 1 4
输出样例#1:
1
输入样例#2:
4 1 3 4 2 1 7 2 4
输出样例#2:
2
说明
【输入输出样例说明1】
最小距离是 0,最少需要交换 1 次,比如:交换第 1 列的前 2 根火柴或者交换第 2 列的前 2 根火柴。
【输入输出样例说明2】
最小距离是 10,最少需要交换 2 次,比如:交换第 1 列的中间 2 根火柴的位置,再交换第 2 列中后 2 根火柴的位置。
【数据范围】
对于 10%的数据, 1 ≤ n ≤ 10;
对于 30%的数据,1 ≤ n ≤ 100;
对于 60%的数据,1 ≤ n ≤ 1,000;
对于 100%的数据,1 ≤ n ≤ 100,000,0 ≤火柴高度≤ maxlongint
【题解】
十分显然
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #define min(a, b) ((a) < (b) ? (a) : (b)) 7 8 inline void read(int &x) 9 { 10 x = 0;char ch = getchar(), c = ch; 11 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 12 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 13 if(c == '-') x = -x; 14 } 15 16 inline void swap(int &a, int &b) 17 { 18 int tmp = a;a = b;b = tmp; 19 } 20 21 const int MAXN = 10000 + 10; 22 const int MAXM = 50000 + 10; 23 const int INF = 0x3f3f3f3f; 24 25 int n,m,u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],q,s,t,fa[MAXN],b[MAXM]; 26 27 bool cmp(int a, int b) 28 { 29 return w[a] > w[b]; 30 } 31 32 struct Edge 33 { 34 int u,v,w,next; 35 Edge(int _u, int _v, int _w, int _next){u = _u, v = _v, w = _w, next = _next;} 36 Edge(){} 37 }edge[MAXN << 1]; 38 int head[MAXN], cntt; 39 inline void insert(int a, int b, int c) 40 { 41 edge[++cntt] = Edge(a,b,c,head[a]); 42 head[a] = cntt; 43 } 44 45 int deep[MAXN], p[20][MAXN], mi[20][MAXN]; 46 47 void dfs(int u) 48 { 49 b[u] = 1; 50 for(register int pos = head[u];pos;pos = edge[pos].next) 51 { 52 int v = edge[pos].v; 53 if(b[v])continue; 54 deep[v] = deep[u] + 1; 55 p[0][v] = u; 56 mi[0][v] = edge[pos].w; 57 dfs(v); 58 } 59 } 60 61 void yuchuli() 62 { 63 int M = 0; 64 while((1 << M) <= n) ++ M; 65 -- M; 66 for(register int i = 1;i <= M;++ i) 67 for(register int j = 1;j <= n;++ j) 68 p[i][j] = p[i - 1][p[i - 1][j]]; 69 for(register int i = 1;i <= M;++ i) 70 for(register int j = 1;j <= n;++ j) 71 mi[i][j] = min(mi[i - 1][p[i - 1][j]], mi[i - 1][j]); 72 } 73 74 int LCA(int va, int vb) 75 { 76 if(deep[va] < deep[vb]) swap(va, vb); 77 int M = 0; 78 while((1 << M) <= n)++ M; 79 -- M; 80 for(register int i = M;i >= 0;-- i) 81 if(deep[vb] + (1 << i) <= deep[va]) 82 va = p[i][va]; 83 if(va == vb)return va; 84 M = 0; 85 while((1 << M) <= deep[va]) ++ M; 86 -- M; 87 for(register int i = M;i >= 0;-- i) 88 if(p[i][va] != p[i][vb]) 89 { 90 va = p[i][va]; 91 vb = p[i][vb]; 92 } 93 return p[0][va]; 94 } 95 96 int find(int x) 97 { 98 return x == fa[x] ? x : fa[x] = find(fa[x]); 99 } 100 101 int main() 102 { 103 read(n), read(m); 104 for(register int i = 1;i <= m;++i) 105 read(u[i]), read(v[i]), read(w[i]), cnt[i] = i; 106 for(register int i = 1;i <= n;++ i) 107 fa[i] = i; 108 std::sort(cnt + 1, cnt + 1 + m, cmp); 109 for(register int i = 1;i <= m;++i) 110 { 111 int f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]); 112 if(f1 != f2) 113 { 114 fa[f1] = f2; 115 insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]); 116 insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]); 117 } 118 } 119 for(register int i = 1;i <= n;++ i) 120 { 121 if(!b[i]) 122 { 123 deep[i] = 1; 124 dfs(i); 125 } 126 } 127 yuchuli(); 128 read(q); 129 int s,t; 130 int M = 0; 131 while((1 << M) <= n) ++ M; 132 -- M; 133 for(register int i = 1;i <= q;++ i) 134 { 135 read(s), read(t); 136 int f1 = find(s), f2 = find(t); 137 if(f1 != f2) 138 { 139 printf("-1\n"); 140 continue; 141 } 142 int lca = LCA(s, t); 143 int mi1 = INF, mi2 = INF; 144 for(register int j = M;j >= 0;-- j) 145 if(p[j][s] && deep[p[j][s]] >= deep[lca]) 146 { 147 mi1 = min(mi1, mi[j][s]); 148 s = p[j][s]; 149 } 150 for(register int j = M;j >= 0;-- j) 151 if(p[j][t] && deep[p[j][t]] >= deep[lca]) 152 { 153 mi2 = min(mi2, mi[j][t]); 154 t = p[j][t]; 155 } 156 printf("%d\n", min(mi1, mi2)); 157 } 158 return 0; 159 }