逆序对

逆序对

求任意两个区间之间所形成的逆序对的个数

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;
}
//规定逆序对的对数,求解有多少序列满足该条件
f[1][0]=1,f[2][0]=1,f[2][1]=1;
for(int i=3;i<=n;i++){
for(int j=0;j<=m;j++){
for(int k=0;k<i&&j-k>=0;k++){
f[i][j]=(f[i][j]+f[i-1][j-k])%10000;
}
}
}

二、数码问题

规定一个状态的逆序为:除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;
for(int i=1;i<=n*n;i++){
int x; scanf("%d",&x);
if(x) a[ii++]=x;
else ans=i;
}
ans=n-((ans-1)/n+1);
merge(1,n*n-1);
if(n%2){
if(cnt%2==0) printf("YES\n");
else printf("NO\n");
}else{
if((ans+cnt)%2==0) printf("YES\n");
else printf("NO\n");
}
}



return 0;
}

三、树状数组的求法

posted @ 2022-02-26 23:21  fengzlj  阅读(158)  评论(0)    收藏  举报