您的位置:首页 > 其它

URAL 1090. In the Army Now

2014-08-28 21:34 225 查看




题意:求逆序数对。输出逆序数对最大的一行的标号,若有多行,输出其中行数最小的一行的标号。

方法一:划分区间,由于每个数的范围都是1-N。肯定小于10000.

将10000分成100个区间,记录1-10000每个值有几个,再记录每个区间内有几个。

对于每个值,只要知道它之前的数中有多少个比它大就行了

每次搜索最多100个区间+100个值 =200次.

方法二:归并排序顺便求逆序数对。

方法一代码:

int ALL,ANS,tempA;
int h[10101];
int Ih[102];
int N,K;
int main(void)
{
while(cin>>N>>K){

ALL=-1;ANS=1;
for(int i=0;i<K;i++){
memset(h,0,sizeof(h));memset(Ih,0,sizeof(Ih));
tempA=0;
for(int j=0;j<N;j++){
int temp;
scanf("%d",&temp);
for(int i=temp;i<temp/100*100+100;i++) tempA+=h[i];
for(int i=temp/100+1;i<=101;i++) tempA+=Ih[i];
h[temp]++;Ih[temp/100]++;
}
if(~ALL) {
if(tempA>ALL) ALL=tempA,ANS=i+1;
}
else ALL=tempA,ANS=i+1;
}
cout<<ANS<<endl;
}
return 0;
}

方法二代码:

int R[20][10000];
int N,K;
int rank[10000];
int merge(int a[],int lo,int hi){
if(lo>=hi) return 0;
int mid=lo+(hi-lo)/2,ANS=0;
ANS+=merge(a,lo,mid);
ANS+=merge(a,mid+1,hi);
int *b=new int[mid-lo+1];
int *c=new int[hi-mid];
for(int i=0;i<mid-lo+1;i++) b[i]=a[lo+i];
for(int i=0;i<hi-mid;i++) c[i]=a[i+mid+1];
int Ib=0,Ic=0,Ia=0;
while(Ia<hi-lo+1){
if(Ib <mid-lo+1&&Ic < hi-mid){
if(b[Ib]>c[Ic]) a[lo+Ia++]=c[Ic++],ANS+=mid-lo+1-Ib;
else a[lo+Ia++]=b[Ib++];
}
else if(Ib <mid-lo+1){
a[lo+Ia++]=b[Ib++];
}
else if(Ic<hi-mid){
a[lo+Ia++]=c[Ic++];
}
}
delete []b;
delete []c;
return ANS;
}
int main(void)
{
while(cin>>N>>K){
for(int i=0;i<K;i++){
for(int j=0;j<N;j++){
scanf("%d",&R[i][j]);
}
}
int ANS=merge(R[0],0,N-1);int ANSI=0;
for(int i=0;i<K;i++){
int D=merge(R[i],0,N-1);
if(D >ANS) ANS=D,ANSI=i;
}
cout<<ANSI+1<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Ural