您的位置:首页 > 其它

树状数组---逆序类题目

2016-08-10 20:38 281 查看

1. POJ 2299 Ultra-QuickSort(树状数组逆序+离散化)

题目链接:http://poj.org/problem?id=2299

题意: 给出长度为n的序列,每次只能交换相邻的两个元素,问至少要交换几次才使得该序列为递增序列?

题解:其实就是求逆序对的数量。可以用树状数组来求。虽然数的大小为 999,999,999,但是数的规模只有500,000,所以可以对数据进行离散化,之后就可以用树状数组来求了。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX=500000+5;
typedef long long LL;
int bit[MAX];
int a[MAX];
int tmp[MAX];
int N;
int sum(int x)
{
int sum=0;
while(x>0)
{
sum+=bit[x];
x-=(x&(-x));
}
return sum;
}
void add(int x,int value)
{
while(x<=N)
{
bit[x]+=value;
x+=(x&(-x));
}
}
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
memset(bit,0,sizeof(bit));
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
tmp[i]=a[i];
}
N=n;
sort(tmp,tmp+n);
for(int i=0;i<n;i++)
{
a[i]=lower_bound(tmp,tmp+n,a[i])-tmp+1;
}
LL ans=0;
for(int i=n-1;i>=0;i--)
{
ans=ans+sum(a[i]);
add(a[i],1);
}
cout<<ans<<endl;
}
return 0;
}

2.HDU 1394 Minimum Inversion Number(树状数组逆序)

题目链接:点击打开链接

题意:给定一个序列,对该序列的n种排列(排列如下)的每种排列的逆序数求最大值:

a1, a2, ..., an-1, an  

a2, a3, ..., an, a1  

a3, a4, ..., an, a1, a2 

 ...  

an, a1, a2, ..., an-1 

题解:

我们可以分为n步,每次都将第一个元素移动到最后一个,这样原来的逆序对变为顺序对,原来的顺序对变为逆序对,所以逆序对减少的数量为(比他小的数的个数)减去(比他大的数的个数),即cnt-(n-1-cnt)=2*cnt-n+1,cnt为比当前数小的数,cnt可以用树状数组求出,但是因为每次操作的都是第一个数,并且数只有1-n,所以cnt就等于a[i]-1。cnt-(n-1-cnt)=2*cnt-n+1=2*a[i]-n-1。进行n步求出逆序对减少的数量的最大值用总的逆序对数减去这个值即可。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int MAX=5000+5;
const int INF=0x3f3f3f3f;
typedef long long LL;
int a[MAX];
int rs[MAX];
int bit[MAX];
int N;
int sum(int x)
{
int s=0;
while(x>0)
{
s+=bit[x];
x-=(x&(-x));
}
return s;
}
void add(int x,int v)
{
while(x<=N)
{
bit[x]+=v;
x+=(x&(-x));
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(bit,0,sizeof(bit));
N=n;
int tol=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]++;
tol+=sum(N)-sum(a[i]);
add(a[i],1);
}
int mmax=0;
int cur=0;
for(int i=0;i<n-1;i++)
{
/* int cnt=sum(a[i]-1);
cur+=cnt-(n-1-cnt);*/
cur+=2*a[i]-n-1;
mmax=max(mmax,cur);
}
printf("%d\n",tol-mmax);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  树状数组 逆序