输入:
第一行一个数N,代表输入的数有N个。
第二行N个正整数
以后K行:
左区间值与右区间值,以空格隔开。回车结束该行输入。
结束输入:
换行,CTRL+Z
#include
#include
#include
#include
#include
using namespace std;
#define lowbit(x) x&-x
int N;
void UPDATE(int*Tree,int k,int x)//更改某点数值
{
for(int i=k;i<=N;)
{
Tree[i]+=x;
i+=lowbit(i);
}
}
int ALL(int*Tree,int k)//1~N求和
{
int Num=0;
for(int i=k;i>=1;)
{
Num+=Tree[i];
i-=lowbit(i);
}
return Num;
}
int main()
{
scanf("%d",&N);
int*Tree=(int*)malloc(sizeof(int)*(N+2));
fill(Tree,Tree+(N+2),0);
int key;
for(int i=1;i<=N;i++)
{
scanf("%d",&key);
UPDATE(Tree,i,key);
}
int x,y;
while(scanf("%d%d",&x,&y)!=EOF)
printf("%d\n",ALL(Tree,y)-ALL(Tree,x-1));
return 0;
}
理论上,如果没有数据限制,用树状数组解决Ultra-QuickSort无疑是非常好的办法,但我们遇到了一个拦路虎,因为0 ≤ a[i] ≤ 999,999,999,这样大的数据范围是无法开出这么长的数组的,就算能够实现,在实际工程问题中,这样的办法也及其耗费资源,并不是一种经济的办法。
就仅这道题而言,仅仅因为数据范围就用不了树状数组实在是有点可惜。虽然我们无法开出10的9次方的数组,但由于数字的总量很小,如果我们在不改变大小关系的前提下将各个数字“缩小”,直到能够运用树状数组来解决就可以啦。缩小到什么程度最好呢?当然是排序后的每对相邻的数字只相差1,就能最大程度的节约内存啦。
当我们把输入的数据排序好以后,将他们的值都依顺序改为1,2,3,4,5,。。。然后再逆排序,即变成输入顺序就可以啦。这个操作我是用一个结构体和一个额外数组完成的。具体可以看代码。
题目百度即可
#include
#include
#include
#include
#include
using namespace std;
#define lowbit(x) x&-x
int N;
struct Doc
{
long long num;
int doc;
};
bool cmp(Doc a,Doc b)
{
return a.numvoid UPDATE(int*Tree,int k,int x)
{
for(int i=k;i<=N;)
{
Tree[i]+=x;
i+=lowbit(i);
}
}
int SUM(int*Tree,int k)
{
int sum=0;
for(int i=k;i>=1;)
{
sum+=Tree[i];
i-=lowbit(i);
}
return sum;
}
void RESET(Doc*ToTran,int*Array)
{
sort(ToTran+1,ToTran+N+1,cmp);
for(int i=1;i<=N;i++)
{
Array[ToTran[i].doc]=i;
}
}
long long BDans(int*Array,int*Tree)
{
long long ans=0;
for(int i=1;i<=N;i++)
{
//printf("现在插入%d\n",Array[i]);
UPDATE(Tree,Array[i],1);
//printf("%d当前SUM是%d\n",i,SUM(Tree,i));
ans+=i-SUM(Tree,Array[i]);
//printf("目前积累%d\n",ans);
}
return ans;
}
int main()
{
while(scanf("%d",&N)!=EOF && N)
{
Doc*ToTran=(Doc*)malloc(sizeof(Doc)*(N+2));
int*Array=(int*)malloc(sizeof(int)*(N+2));
int*Tree=(int*)malloc(sizeof(int)*(N+2));
fill(Tree,Tree+(N+2),0);
for(int i=1;i<=N;i++)
{
scanf("%I64d",&ToTran[i].num);
ToTran[i].doc=i;
}
RESET(ToTran,Array);
printf("%I64d\n",BDans(Array,Tree));
}
return 0;
}
之前没有想到可以对数据大小进行改变,而误认为不能用树状数组解决这题,实在对不起之前的读者。。。