Description
第一题
第二题
第三题
题解
T1
你会发现,我们可以先固定一个序列a,然后把另外一个序列b按照a的顺序标一下号。
然后题意就变成了求b的逆序对数。
而首尾交换其实就是这样:
假设当前交换的数为
i
i
i,那么逆序对数
a
n
s
=
a
n
s
+
(
i
−
1
)
−
(
n
−
i
)
ans=ans+(i-1)-(n-i)
ans=ans+(i−1)−(n−i)
也就是加上小于i的数的个数,减去大于i的数的个数。
那么两个序列都做一遍就好了。
T2
先列一个 O ( n 3 ) O(n^3) O(n3)的方程。
由于我们的限制是小于4的。
那么意味着我们只有9种转移的状态。
然后我们再随便用一下树状数组维护一下即可。
T3
这题可谓是最难且最为麻烦的一道了吧。(相对的,其实还是很基础)
其实我们发现,我们只要满足三个条件就对答案有贡献:
a
[
i
]
>
a
[
j
]
a[i]>a[j]
a[i]>a[j]
b
[
i
]
<
b
[
j
]
b[i]<b[j]
b[i]<b[j]
a
b
s
(
i
−
j
)
<
=
K
abs(i-j)<=K
abs(i−j)<=K
裸的三维偏序。
然后我™考试的时候以为数组越界没切。
好菜啊~
标程
T1
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=100010;
int n,m,a[maxn],b[maxn],d[maxn],e[maxn],jlb[maxn];
long long c[maxn*10];
int lowbit(int x)
{
return x&(-x);
}
void modify(int i,long long k)
{
while (i<=n)
{
c[i]=(c[i]+k);
i+=lowbit(i);
}
}
long long getans(int i)
{
long long gg=0;
int kk=0;
while (i>0)
{
gg=(gg+c[i]);
kk=lowbit(i);
i-=kk;
}
return gg;
}
int main()
{
freopen("mincross.in","r",stdin);
freopen("mincross.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
e[a[i]]=i;
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
jlb[i]=b[i];
d[b[i]]=i;
}
for (int i=1;i<=n;i++)
{
b[d[a[i]]]=n-i+1;
modify(i,1);
}
long long ans=0;
long long op=n;
long long answer=op*op;
for (int i=1;i<=n;i++)
{
ans+=n-i+1-getans(b[i]);
modify(b[i],-1);
}
answer=min(answer,ans);
for (int i=n;i>1;i--)
{
ans+=(n-b[i])-(b[i]-1);
answer=min(answer,ans);
}
for (int i=1;i<=n;i++)
{
a[e[jlb[i]]]=n-i+1;
modify(i,1);
}
ans=0;
for (int i=1;i<=n;i++)
{
ans+=n-i+1-getans(a[i]);
modify(a[i],-1);
}
answer=min(answer,ans);
for (int i=n;i>1;i--)
{
ans+=(n-a[i])-(a[i]-1);
answer=min(answer,ans);
}
printf("%lld\n",answer);
}
T2
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=100010;
int n,m,a[maxn],b[maxn],id[maxn],ans[maxn],jlb[maxn];
long long c[maxn*10];
void qsort(int l,int r)
{
int i=l;int j=r;
int m=b[(i+j)/2];
while (i<=j)
{
while (b[i]<m) i++;
while (b[j]>m) j--;
if (i<=j)
{
swap(id[i],id[j]);
swap(b[i],b[j]);
i++;j--;
}
}
if (l<j) qsort(l,j);
if (r>i) qsort(i,r);
}
int lowbit(int x)
{
return x&(-x);
}
void modify(int i,long long k)
{
while (i<=n)
{
if (c[i]>=k) return;
c[i]=(k);
i+=lowbit(i);
}
}
long long getans(int i)
{
long long gg=0;
int kk=0;
while (i>0)
{
gg=max(gg,c[i]);
kk=lowbit(i);
i-=kk;
}
return gg;
}
int main()
{
freopen("nocross.in","r",stdin);
freopen("nocross.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
id[b[i]]=i;
}
for (int i=1;i<=n;i++)
{
int st=max(1,a[i]-4);
int en=min(n,a[i]+4);
for (int j=st;j<=en;j++)
{
ans[j]=getans(id[j]-1);
}
for (int j=st;j<=en;j++)
{
modify(id[j],ans[j]+1);
}
}
printf("%d\n",getans(n));
}
T3
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int maxn=200010;
int n,m,a[maxn],b[maxn],id[maxn],x[maxn],y[maxn],p[3][maxn],q[3][maxn],jl[100][3][maxn];
long long c[maxn*10],ans;
void qsort(int l,int r)
{
int i=l;int j=r;
int m=x[(i+j)/2];
while (i<=j)
{
while (x[i]<m) i++;
while (x[j]>m) j--;
if (i<=j)
{
swap(x[i],x[j]);
// swap(id[i],id[j]);
i++;j--;
}
}
if (l<j) qsort(l,j);
if (r>i) qsort(i,r);
}
int lowbit(int x)
{
return x&(-x);
}
void modify(int i,long long k)
{
while (i<=n)
{
c[i]=(c[i]+k);
i+=lowbit(i);
}
}
long long getans(int i)
{
long long gg=0;
int kk=0;
while (i>0)
{
gg=(gg+c[i]);
kk=lowbit(i);
i-=kk;
}
return gg;
}
void solve(int dep,int ki,int l,int r)
{
if (l==r)
{
p[ki][0]=1;
p[ki][1]=id[l];
}
else
{
int mid=(l+r)/2;
solve(dep+1,1,l,mid);
for (int i=0;i<=p[1][0];i++) jl[dep][1][i+l]=p[1][i];
solve(dep+1,2,mid+1,r);
for (int i=0;i<=p[2][0];i++) q[2][i]=p[2][i];
for (int i=0;i<=jl[dep][1][l];i++) q[1][i]=jl[dep][1][i+l];
int xx=1;int yy=1;
p[ki][0]=0;
while (yy<=q[2][0])
{
while (y[q[2][yy]]<y[q[1][xx]] && xx<=q[1][0])
{
modify(q[1][xx],1);
p[ki][0]++;p[ki][p[ki][0]]=q[1][xx];
xx++;
}
p[ki][0]++;p[ki][p[ki][0]]=q[2][yy];
ans+=getans(q[2][yy]-m-1);
ans+=xx-1-getans(min(n,q[2][yy]+m));
yy++;
}
for (int i=1;i<=xx-1;i++)
{
modify(q[1][i],-1);
}
while (xx<=q[1][0])
{
p[ki][0]++;p[ki][p[ki][0]]=q[1][xx];
xx++;
}
}
}
int main()
{
freopen("friendcross.in","r",stdin);
freopen("friendcross.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
x[a[i]]=i;
id[i]=a[i];
}
for (int i=1;i<=n;i++)
{
scanf("%d",&b[i]);
y[b[i]]=i;
}
qsort(1,n);
solve(1,1,1,n);
printf("%lld\n",ans);
}