1 条题解
-
0
思路
首先, 和 只会移动一个,那么,我们分开来算,我们先假定 会动。
不妨令 与 连边的端点为 。如果有线段 能与 相交,一定满足如下其中一条规律:
发现每一次循环右移一次,只会影响一条端点在 的位置的线段,其余线段相对位置不变。
令 在 中的位置为 。因为 是在 中的最后一个元素,所以如果有线段能与其所在线段相交,那么只能是满足上述规律中的第 2 种。所以所有以 为端点的线段一定与 所在线段相交。
那么,如果我们将 循环右移一位后,可以发现原本与 相交的线段都不会相交了,即将数量 变为了 。
再来考虑 循环右移到 时会产生新的数量。因为 是 中的第一个元素,所以如果有线段能与其所在线段相交,那么只能是满足上述条件中的第 1 种。所以,所有以 为端点的线段一定与其相交。
那么,我们将 循环右移一位后,可以发现能新产生 条线段,即将数量 变为了 。
那么结果 将变为 。
接下来只需要处理出 在不动时的结果即可。
我们将 表示 在 中的位置,可以发现当 时就会产生一条相交的线段对。然后发现本质上就是求 的逆序对数量,用树状数组算一下即可。
注意:不要忘了讨论 动的情况。
code
#include <bits/stdc++.h> #define re register #define int long long using namespace std; const int N = 1e5 + 10; int n,ans,t; int arr[N],brr[N],vis[N],pos[N]; inline int read(){ int r = 0,w = 1; char c = getchar(); while (c < '0' || c > '9'){ if (c == '-') w = -1; c = getchar(); } while (c >= '0' && c <= '9'){ r = (r << 3) + (r << 1) + (c ^ 48); c = getchar(); } return r * w; } struct BIT{ int tr[N]; inline int lowbit(int x){ return x & -x; } inline void modify(int x,int k){ for (re int i = x;i <= n;i += lowbit(i)) tr[i] += k; } inline int query(int x){ int res = 0; for (re int i = x;i;i -= lowbit(i)) res += tr[i]; return res; } }tree; inline int f(int *arr,int *brr){ for (re int i = 1;i <= n;i++) vis[arr[i]] = i; for (re int i = 1;i <= n;i++) pos[i] = vis[brr[i]]; int res = 0,ans = 0; memset(tree.tr,0,sizeof(tree.tr)); for (re int i = n;i;i--){ res += tree.query(pos[i]); tree.modify(pos[i],1); } ans = res; for (re int i = n;i;i--){ res = res - n + 2 * pos[i] - 1; ans = min(ans,res); } return ans; } signed main(){ n = read(); for (re int i = 1;i <= n;i++) arr[i] = read(); for (re int i = 1;i <= n;i++) brr[i] = read(); printf("%lld",min(f(arr,brr),f(brr,arr))); return 0; }
- 1
信息
- ID
- 6847
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 10
- 标签
- 递交数
- 11
- 已通过
- 1
- 上传者