逆序对
求任意两个区间之间所形成的逆序对的个数
LL calc(Node x,Node y)
{
LL l=max(x.l,y.l);
if(l>x.r) return 0;
LL r=min(x.r,y.r);
LL ans=(l-y.l+r-y.l)*(r-l+1)/2%mod;
ans=(ans+(x.r-r)*(y.r-y.l+1))%mod;
return ans;
}
一、归并排序
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=5e5+100;
int a[MAXN],b[MAXN];
LL cnt=0;
void merge(int l,int r)
{
if(l>=r) return ;
int mid=(l+r)>>1;
merge(l,mid);
merge(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r){
if(a[i]<=a[j]) b[k++]=a[i++];
else b[k++]=a[j++],cnt+=mid-i+1;
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(int ii=0;ii<k;ii++) a[ii+l]=b[ii];
return ;
}
int main()
{
int n; scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
merge(1,n);
printf("%lld\n",cnt);
return 0;
}
二、数码问题
规定一个状态的逆序为:除0之外的所有数字的逆序数之和。
初始状态的逆序为0(偶数);如果两个状态的逆序的奇偶性相同,可以互相转化。
八数码问题:如果一个状态的逆序为偶数则有解。
n*n问题:n为奇数时,逆序奇偶性相同可达;
定义空格的距离:空格位置所在的行到目标空格所在的行步数
n为偶数时,逆序奇偶性一致和空格距离为偶数;逆序奇偶性不同且空格距离为奇数可达
n * n * n问题:n为奇数,逆序奇偶性相同可达;
定义空格的距离:空格所在位置的yz方向的距离和
n为偶数时,逆序奇偶性一致和空格距离为偶数;逆序奇偶性不同且空格距离为奇数可达
注意点:1)关于n的分类,
2)统计可能的情况的int会爆,要用LL
3)图的直接用以为存储的时候空格位不存储
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN=9e4+100;
int a[MAXN],b[MAXN];
LL cnt=0;
void merge(int l,int r)
{
if(l>=r) return ;
int mid=(l+r)>>1;
merge(l,mid);
merge(mid+1,r);
int i=l,j=mid+1,k=0;
while(i<=mid&&j<=r){
if(a[i]<=a[j]) b[k++]=a[i++];
else b[k++]=a[j++],cnt+=mid-i+1;
}
while(i<=mid) b[k++]=a[i++];
while(j<=r) b[k++]=a[j++];
for(int ii=0;ii<k;ii++) a[ii+l]=b[ii];
return ;
}
void init()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cnt=0;
return ;
}
int main()
{
int n;
while(~scanf("%d",&n)){
if(n==0) break;
init();
int ans=0;
int ii=1;