Why Did the Cow Cross the Road I P 题解
Posted groundwater
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Why Did the Cow Cross the Road I P 题解相关的知识,希望对你有一定的参考价值。
老早之前做的,补题解。
简化の题意
给两个长度为 (n) 的排列 (A),(B),允许对任意一个排列进行一次旋转
定义为(egin{cases}A_igets A_{i-1}&i<n \A_ngets A_1end{cases})
设四元组 ({i,j,k,l} (ileq kleq n,jleq l leq n)) 满足(egin{cases}A_i=B_j\A_k=B_lend{cases}) 求四元组的最小数量 复杂erの题意。
思路
首先我们发现这两个排列可以表示成一个排列,以样例为例:
A:5 4 1 3 2
B:1 3 2 5 4
把 (A o B) 的映射关系建立一下(所以其实有两种表示方法,这里暂时只考虑一种),就得到
4 5 1 2 3
明显的,满足题意的四元组的个数为这个排列的逆序对的个数。
接下来考虑旋转,上图:
设当前Pre点移动到New点,所以我们要销毁红色边,新建蓝色边。从图中可以看出,绿色的边将不再与红色的边交叉,而橙色的边将与新的蓝色边交叉,所以旋转后的的答案将减2。也即减去第二排左边的点再加上右边的点。
注意到第二排的点不会改变位置,所以每一次旋转并不会影响其他旋转的答案,所以,对于每一次旋转,我们都可以 (O(1)) 求出旋转后的答案。
一个重要的地方:两排的旋转并不等价,所以要分别对两边求两次解。
代码
#include<cstdio>
#include<iostream>
#define lowb(x)(x&-x)
using namespace std;
int n,a[100010],b[100010],c[100010],t[100010];
long long ans=0x7fffffffffffffff,sum;
void read(int &x){
char c=getchar();
for(;c<33;c=getchar());
for(x=0;(47<c)&&(c<58);x=x*10+c-48,c=getchar());
}
void sg(int x,int c){
for(;x<=n;x+=lowb(x)){
t[x]+=c;
}
}
int call(int x){
int re=0;
for(;x;x-=lowb(x)){
re+=t[x];
}
return(re);
}
void solve(int *a,int *b){
for(int i=1;i<=n;i++){
c[b[i]]=i;
t[i]=0;
}
sum=0;
for(int i=1;i<=n;i++){
sum+=call(n-c[a[i]]+1);
sg(n-c[a[i]]+1,1);
}
for(int i=1;i<=n;i++){
sum-=c[a[i]]-1;
sum+=n-c[a[i]];
ans=min(ans,sum);
}
}
int main(){
freopen("mincross.in","r",stdin);
freopen("mincross.out","w",stdout);
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
for(int i=1;i<=n;i++){
read(b[i]);
}
solve(a,b);
solve(b,a);
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
return(0);
}
以上是关于Why Did the Cow Cross the Road I P 题解的主要内容,如果未能解决你的问题,请参考以下文章
Why Did the Cow Cross the Road I P 题解
USACO 2017 FEB Why Did the Cow Cross the Road III G
洛谷 P3663 [USACO17FEB]Why Did the Cow Cross the Road III S
洛谷 P3659 [USACO17FEB]Why Did the Cow Cross the Road I G
[BZOJ4989] [Usaco2017 Feb]Why Did the Cow Cross the Road(树状数组)